diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp new file mode 100644 index 0000000..33d8e99 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -0,0 +1,935 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// GLFW +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include +#ifdef _WIN32 +#undef APIENTRY +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "imgui_impl_glfw_vulkan.h" + +// GLFW Data +static GLFWwindow* g_Window = NULL; +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; + +// Vulkan Data +static VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; + +static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; +static size_t g_BufferMemoryAlignment = 256; +static VkPipelineCreateFlags g_PipelineCreateFlags = 0; +static int g_FrameIndex = 0; + +static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; +static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; +static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; +static VkPipeline g_Pipeline = VK_NULL_HANDLE; + +static VkSampler g_FontSampler = VK_NULL_HANDLE; +static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; +static VkImage g_FontImage = VK_NULL_HANDLE; +static VkImageView g_FontView = VK_NULL_HANDLE; + +static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; + +static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; +static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; + +static unsigned char __glsl_shader_vert_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, + 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x41, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x06, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7f, 0x02, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x7f, 0x02, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x2e, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x60, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x41, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0xaa, 0x26, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xaa, 0x26, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x91, 0x02, 0x00, 0x00, + 0xea, 0x50, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xea, 0x50, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0xa1, 0x41, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x84, 0x36, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xa1, 0x41, 0x00, 0x00, 0x84, 0x36, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0x17, 0x2f, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_vert_spv_len = 1172; + +static unsigned char __glsl_shader_frag_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x7a, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x04, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x03, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x5d, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x0b, 0x40, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x90, 0x02, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x35, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x57, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xb9, 0x46, 0x00, 0x00, + 0xc0, 0x36, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0xe4, 0x23, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x00, + 0xb9, 0x46, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x0c, 0x00, 0x00, + 0xe4, 0x23, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_frag_spv_len = 660; + +static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<TotalVtxCount * sizeof(ImDrawVert); + if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) + { + if (g_VertexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); + if (g_VertexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); + size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; + } + + // Create the Index Buffer: + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) + { + if (g_IndexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); + if (g_IndexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); + size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = index_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_IndexBufferSize[g_FrameIndex] = index_buffer_size; + } + + // Upload Vertex and index Data: + { + ImDrawVert* vtx_dst; + ImDrawIdx* idx_dst; + err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].size = vertex_size; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].size = index_size; + err = vkFlushMappedMemoryRanges(g_Device, 2, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + } + + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = {g_DescriptorSet}; + vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; + VkDeviceSize vertex_offset[1] = {0}; + vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + } + + // Setup scale and translation: + { + float scale[2]; + scale[0] = 2.0f/io.DisplaySize.x; + scale[1] = 2.0f/io.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f; + translate[1] = -1.0f; + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + VkRect2D scissor; + scissor.offset.x = static_cast(pcmd->ClipRect.x); + scissor.offset.y = static_cast(pcmd->ClipRect.y); + scissor.extent.width = static_cast(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = static_cast(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? + vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +static const char* ImGui_ImplGlfwVulkan_GetClipboardText() +{ + return glfwGetClipboardString(g_Window); +} + +static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) +{ + glfwSetClipboardString(g_Window, text); +} + +void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +{ + if (action == GLFW_PRESS && button >= 0 && button < 3) + g_MousePressed[button] = true; +} + +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +{ + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. +} + +void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +} + +void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +{ + ImGuiIO& io = ImGui::GetIO(); + if (c > 0 && c < 0x10000) + io.AddInputCharacter((unsigned short)c); +} + +bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) +{ + ImGuiIO& io = ImGui::GetIO(); + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width*height*4*sizeof(char); + + VkResult err; + + // Create the Image: + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.extent.width = width; + info.extent.height = height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetImageMemoryRequirements(g_Device, g_FontImage, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create the Image View: + { + VkResult err; + VkImageViewCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.image = g_FontImage; + info.viewType = VK_IMAGE_VIEW_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.levelCount = 1; + info.subresourceRange.layerCount = 1; + err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Update the Descriptor Set: + { + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = g_FontSampler; + desc_image[0].imageView = g_FontView; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = g_DescriptorSet; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL); + } + + // Create the Upload Buffer: + { + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Upload to Buffer: + { + char* map = NULL; + err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); + ImGui_ImplGlfwVulkan_VkResult(err); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_UploadBufferMemory; + range[0].size = upload_size; + err = vkFlushMappedMemoryRanges(g_Device, 1, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_UploadBufferMemory); + } + // Copy to Image: + { + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = g_FontImage; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = g_FontImage; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); + } + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontImage; + + return true; +} + +bool ImGui_ImplGlfwVulkan_CreateDeviceObjects() +{ + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = __glsl_shader_vert_spv_len; + vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module); + ImGui_ImplGlfwVulkan_VkResult(err); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = __glsl_shader_frag_spv_len; + frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_PipelineLayout) + { + VkPushConstantRange push_constants[2] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 2; + push_constants[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[1].offset = sizeof(float) * 2; + push_constants[1].size = sizeof(float) * 2; + VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 2; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.dynamicStateCount = 2; + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = g_PipelineCreateFlags; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = g_PipelineLayout; + info.renderPass = g_RenderPass; + err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline); + ImGui_ImplGlfwVulkan_VkResult(err); + + vkDestroyShaderModule(g_Device, vert_module, g_Allocator); + vkDestroyShaderModule(g_Device, frag_module, g_Allocator); + + return true; +} + +void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects() +{ + if (g_UploadBuffer) + { + vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator); + g_UploadBuffer = VK_NULL_HANDLE; + } + if (g_UploadBufferMemory) + { + vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator); + g_UploadBufferMemory = VK_NULL_HANDLE; + } +} + +void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() +{ + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + for (int i=0; iallocator; + g_Gpu = init_data->gpu; + g_Device = init_data->device; + g_RenderPass = init_data->render_pass; + g_PipelineCache = init_data->pipeline_cache; + g_DescriptorPool = init_data->descriptor_pool; + g_CheckVkResult = init_data->check_vk_result; + + g_Window = window; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; +#ifdef _WIN32 + io.ImeWindowHandle = glfwGetWin32Window(g_Window); +#endif + + if (install_callbacks) + { + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); + } + + ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplGlfwVulkan_Shutdown() +{ + ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplGlfwVulkan_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + glfwGetWindowSize(g_Window, &w, &h); + glfwGetFramebufferSize(g_Window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + double current_time = glfwGetTime(); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } + else + { + io.MousePos = ImVec2(-1,-1); + } + + for (int i = 0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MousePressed[i] = false; + } + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + + // Start the frame + ImGui::NewFrame(); +} +void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) +{ + g_CommandBuffer = command_buffer; + ImGui::Render(); + g_CommandBuffer = VK_NULL_HANDLE; + g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp new file mode 100644 index 0000000..33d8e99 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -0,0 +1,935 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// GLFW +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include +#ifdef _WIN32 +#undef APIENTRY +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "imgui_impl_glfw_vulkan.h" + +// GLFW Data +static GLFWwindow* g_Window = NULL; +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; + +// Vulkan Data +static VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; + +static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; +static size_t g_BufferMemoryAlignment = 256; +static VkPipelineCreateFlags g_PipelineCreateFlags = 0; +static int g_FrameIndex = 0; + +static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; +static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; +static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; +static VkPipeline g_Pipeline = VK_NULL_HANDLE; + +static VkSampler g_FontSampler = VK_NULL_HANDLE; +static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; +static VkImage g_FontImage = VK_NULL_HANDLE; +static VkImageView g_FontView = VK_NULL_HANDLE; + +static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; + +static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; +static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; + +static unsigned char __glsl_shader_vert_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, + 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x41, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x06, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7f, 0x02, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x7f, 0x02, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x2e, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x60, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x41, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0xaa, 0x26, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xaa, 0x26, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x91, 0x02, 0x00, 0x00, + 0xea, 0x50, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xea, 0x50, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0xa1, 0x41, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x84, 0x36, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xa1, 0x41, 0x00, 0x00, 0x84, 0x36, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0x17, 0x2f, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_vert_spv_len = 1172; + +static unsigned char __glsl_shader_frag_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x7a, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x04, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x03, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x5d, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x0b, 0x40, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x90, 0x02, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x35, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x57, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xb9, 0x46, 0x00, 0x00, + 0xc0, 0x36, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0xe4, 0x23, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x00, + 0xb9, 0x46, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x0c, 0x00, 0x00, + 0xe4, 0x23, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_frag_spv_len = 660; + +static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<TotalVtxCount * sizeof(ImDrawVert); + if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) + { + if (g_VertexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); + if (g_VertexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); + size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; + } + + // Create the Index Buffer: + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) + { + if (g_IndexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); + if (g_IndexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); + size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = index_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_IndexBufferSize[g_FrameIndex] = index_buffer_size; + } + + // Upload Vertex and index Data: + { + ImDrawVert* vtx_dst; + ImDrawIdx* idx_dst; + err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].size = vertex_size; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].size = index_size; + err = vkFlushMappedMemoryRanges(g_Device, 2, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + } + + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = {g_DescriptorSet}; + vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; + VkDeviceSize vertex_offset[1] = {0}; + vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + } + + // Setup scale and translation: + { + float scale[2]; + scale[0] = 2.0f/io.DisplaySize.x; + scale[1] = 2.0f/io.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f; + translate[1] = -1.0f; + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + VkRect2D scissor; + scissor.offset.x = static_cast(pcmd->ClipRect.x); + scissor.offset.y = static_cast(pcmd->ClipRect.y); + scissor.extent.width = static_cast(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = static_cast(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? + vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +static const char* ImGui_ImplGlfwVulkan_GetClipboardText() +{ + return glfwGetClipboardString(g_Window); +} + +static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) +{ + glfwSetClipboardString(g_Window, text); +} + +void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +{ + if (action == GLFW_PRESS && button >= 0 && button < 3) + g_MousePressed[button] = true; +} + +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +{ + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. +} + +void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +} + +void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +{ + ImGuiIO& io = ImGui::GetIO(); + if (c > 0 && c < 0x10000) + io.AddInputCharacter((unsigned short)c); +} + +bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) +{ + ImGuiIO& io = ImGui::GetIO(); + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width*height*4*sizeof(char); + + VkResult err; + + // Create the Image: + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.extent.width = width; + info.extent.height = height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetImageMemoryRequirements(g_Device, g_FontImage, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create the Image View: + { + VkResult err; + VkImageViewCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.image = g_FontImage; + info.viewType = VK_IMAGE_VIEW_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.levelCount = 1; + info.subresourceRange.layerCount = 1; + err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Update the Descriptor Set: + { + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = g_FontSampler; + desc_image[0].imageView = g_FontView; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = g_DescriptorSet; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL); + } + + // Create the Upload Buffer: + { + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Upload to Buffer: + { + char* map = NULL; + err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); + ImGui_ImplGlfwVulkan_VkResult(err); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_UploadBufferMemory; + range[0].size = upload_size; + err = vkFlushMappedMemoryRanges(g_Device, 1, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_UploadBufferMemory); + } + // Copy to Image: + { + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = g_FontImage; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = g_FontImage; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); + } + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontImage; + + return true; +} + +bool ImGui_ImplGlfwVulkan_CreateDeviceObjects() +{ + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = __glsl_shader_vert_spv_len; + vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module); + ImGui_ImplGlfwVulkan_VkResult(err); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = __glsl_shader_frag_spv_len; + frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_PipelineLayout) + { + VkPushConstantRange push_constants[2] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 2; + push_constants[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[1].offset = sizeof(float) * 2; + push_constants[1].size = sizeof(float) * 2; + VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 2; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.dynamicStateCount = 2; + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = g_PipelineCreateFlags; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = g_PipelineLayout; + info.renderPass = g_RenderPass; + err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline); + ImGui_ImplGlfwVulkan_VkResult(err); + + vkDestroyShaderModule(g_Device, vert_module, g_Allocator); + vkDestroyShaderModule(g_Device, frag_module, g_Allocator); + + return true; +} + +void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects() +{ + if (g_UploadBuffer) + { + vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator); + g_UploadBuffer = VK_NULL_HANDLE; + } + if (g_UploadBufferMemory) + { + vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator); + g_UploadBufferMemory = VK_NULL_HANDLE; + } +} + +void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() +{ + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + for (int i=0; iallocator; + g_Gpu = init_data->gpu; + g_Device = init_data->device; + g_RenderPass = init_data->render_pass; + g_PipelineCache = init_data->pipeline_cache; + g_DescriptorPool = init_data->descriptor_pool; + g_CheckVkResult = init_data->check_vk_result; + + g_Window = window; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; +#ifdef _WIN32 + io.ImeWindowHandle = glfwGetWin32Window(g_Window); +#endif + + if (install_callbacks) + { + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); + } + + ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplGlfwVulkan_Shutdown() +{ + ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplGlfwVulkan_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + glfwGetWindowSize(g_Window, &w, &h); + glfwGetFramebufferSize(g_Window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + double current_time = glfwGetTime(); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } + else + { + io.MousePos = ImVec2(-1,-1); + } + + for (int i = 0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MousePressed[i] = false; + } + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + + // Start the frame + ImGui::NewFrame(); +} +void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) +{ + g_CommandBuffer = command_buffer; + ImGui::Render(); + g_CommandBuffer = VK_NULL_HANDLE; + g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h new file mode 100644 index 0000000..74d35a2 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -0,0 +1,40 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct GLFWwindow; + +#define IMGUI_VK_QUEUED_FRAMES 2 + +struct ImGui_ImplGlfwVulkan_Init_Data +{ + VkAllocationCallbacks* allocator; + VkPhysicalDevice gpu; + VkDevice device; + VkRenderPass render_pass; + VkPipelineCache pipeline_cache; + VkDescriptorPool descriptor_pool; + void (*check_vk_result)(VkResult err); +}; + +IMGUI_API bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data); +IMGUI_API void ImGui_ImplGlfwVulkan_Shutdown(); +IMGUI_API void ImGui_ImplGlfwVulkan_NewFrame(); +IMGUI_API void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + +// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) +// Provided here if you want to chain callbacks. +// You can also handle inputs yourself and use those as a reference. +IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c); + diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp new file mode 100644 index 0000000..33d8e99 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -0,0 +1,935 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// GLFW +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include +#ifdef _WIN32 +#undef APIENTRY +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "imgui_impl_glfw_vulkan.h" + +// GLFW Data +static GLFWwindow* g_Window = NULL; +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; + +// Vulkan Data +static VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; + +static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; +static size_t g_BufferMemoryAlignment = 256; +static VkPipelineCreateFlags g_PipelineCreateFlags = 0; +static int g_FrameIndex = 0; + +static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; +static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; +static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; +static VkPipeline g_Pipeline = VK_NULL_HANDLE; + +static VkSampler g_FontSampler = VK_NULL_HANDLE; +static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; +static VkImage g_FontImage = VK_NULL_HANDLE; +static VkImageView g_FontView = VK_NULL_HANDLE; + +static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; + +static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; +static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; + +static unsigned char __glsl_shader_vert_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, + 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x41, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x06, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7f, 0x02, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x7f, 0x02, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x2e, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x60, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x41, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0xaa, 0x26, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xaa, 0x26, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x91, 0x02, 0x00, 0x00, + 0xea, 0x50, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xea, 0x50, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0xa1, 0x41, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x84, 0x36, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xa1, 0x41, 0x00, 0x00, 0x84, 0x36, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0x17, 0x2f, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_vert_spv_len = 1172; + +static unsigned char __glsl_shader_frag_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x7a, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x04, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x03, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x5d, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x0b, 0x40, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x90, 0x02, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x35, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x57, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xb9, 0x46, 0x00, 0x00, + 0xc0, 0x36, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0xe4, 0x23, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x00, + 0xb9, 0x46, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x0c, 0x00, 0x00, + 0xe4, 0x23, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_frag_spv_len = 660; + +static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<TotalVtxCount * sizeof(ImDrawVert); + if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) + { + if (g_VertexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); + if (g_VertexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); + size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; + } + + // Create the Index Buffer: + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) + { + if (g_IndexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); + if (g_IndexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); + size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = index_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_IndexBufferSize[g_FrameIndex] = index_buffer_size; + } + + // Upload Vertex and index Data: + { + ImDrawVert* vtx_dst; + ImDrawIdx* idx_dst; + err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].size = vertex_size; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].size = index_size; + err = vkFlushMappedMemoryRanges(g_Device, 2, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + } + + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = {g_DescriptorSet}; + vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; + VkDeviceSize vertex_offset[1] = {0}; + vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + } + + // Setup scale and translation: + { + float scale[2]; + scale[0] = 2.0f/io.DisplaySize.x; + scale[1] = 2.0f/io.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f; + translate[1] = -1.0f; + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + VkRect2D scissor; + scissor.offset.x = static_cast(pcmd->ClipRect.x); + scissor.offset.y = static_cast(pcmd->ClipRect.y); + scissor.extent.width = static_cast(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = static_cast(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? + vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +static const char* ImGui_ImplGlfwVulkan_GetClipboardText() +{ + return glfwGetClipboardString(g_Window); +} + +static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) +{ + glfwSetClipboardString(g_Window, text); +} + +void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +{ + if (action == GLFW_PRESS && button >= 0 && button < 3) + g_MousePressed[button] = true; +} + +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +{ + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. +} + +void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +} + +void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +{ + ImGuiIO& io = ImGui::GetIO(); + if (c > 0 && c < 0x10000) + io.AddInputCharacter((unsigned short)c); +} + +bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) +{ + ImGuiIO& io = ImGui::GetIO(); + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width*height*4*sizeof(char); + + VkResult err; + + // Create the Image: + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.extent.width = width; + info.extent.height = height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetImageMemoryRequirements(g_Device, g_FontImage, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create the Image View: + { + VkResult err; + VkImageViewCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.image = g_FontImage; + info.viewType = VK_IMAGE_VIEW_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.levelCount = 1; + info.subresourceRange.layerCount = 1; + err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Update the Descriptor Set: + { + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = g_FontSampler; + desc_image[0].imageView = g_FontView; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = g_DescriptorSet; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL); + } + + // Create the Upload Buffer: + { + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Upload to Buffer: + { + char* map = NULL; + err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); + ImGui_ImplGlfwVulkan_VkResult(err); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_UploadBufferMemory; + range[0].size = upload_size; + err = vkFlushMappedMemoryRanges(g_Device, 1, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_UploadBufferMemory); + } + // Copy to Image: + { + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = g_FontImage; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = g_FontImage; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); + } + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontImage; + + return true; +} + +bool ImGui_ImplGlfwVulkan_CreateDeviceObjects() +{ + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = __glsl_shader_vert_spv_len; + vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module); + ImGui_ImplGlfwVulkan_VkResult(err); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = __glsl_shader_frag_spv_len; + frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_PipelineLayout) + { + VkPushConstantRange push_constants[2] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 2; + push_constants[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[1].offset = sizeof(float) * 2; + push_constants[1].size = sizeof(float) * 2; + VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 2; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.dynamicStateCount = 2; + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = g_PipelineCreateFlags; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = g_PipelineLayout; + info.renderPass = g_RenderPass; + err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline); + ImGui_ImplGlfwVulkan_VkResult(err); + + vkDestroyShaderModule(g_Device, vert_module, g_Allocator); + vkDestroyShaderModule(g_Device, frag_module, g_Allocator); + + return true; +} + +void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects() +{ + if (g_UploadBuffer) + { + vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator); + g_UploadBuffer = VK_NULL_HANDLE; + } + if (g_UploadBufferMemory) + { + vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator); + g_UploadBufferMemory = VK_NULL_HANDLE; + } +} + +void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() +{ + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + for (int i=0; iallocator; + g_Gpu = init_data->gpu; + g_Device = init_data->device; + g_RenderPass = init_data->render_pass; + g_PipelineCache = init_data->pipeline_cache; + g_DescriptorPool = init_data->descriptor_pool; + g_CheckVkResult = init_data->check_vk_result; + + g_Window = window; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; +#ifdef _WIN32 + io.ImeWindowHandle = glfwGetWin32Window(g_Window); +#endif + + if (install_callbacks) + { + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); + } + + ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplGlfwVulkan_Shutdown() +{ + ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplGlfwVulkan_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + glfwGetWindowSize(g_Window, &w, &h); + glfwGetFramebufferSize(g_Window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + double current_time = glfwGetTime(); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } + else + { + io.MousePos = ImVec2(-1,-1); + } + + for (int i = 0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MousePressed[i] = false; + } + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + + // Start the frame + ImGui::NewFrame(); +} +void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) +{ + g_CommandBuffer = command_buffer; + ImGui::Render(); + g_CommandBuffer = VK_NULL_HANDLE; + g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h new file mode 100644 index 0000000..74d35a2 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -0,0 +1,40 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct GLFWwindow; + +#define IMGUI_VK_QUEUED_FRAMES 2 + +struct ImGui_ImplGlfwVulkan_Init_Data +{ + VkAllocationCallbacks* allocator; + VkPhysicalDevice gpu; + VkDevice device; + VkRenderPass render_pass; + VkPipelineCache pipeline_cache; + VkDescriptorPool descriptor_pool; + void (*check_vk_result)(VkResult err); +}; + +IMGUI_API bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data); +IMGUI_API void ImGui_ImplGlfwVulkan_Shutdown(); +IMGUI_API void ImGui_ImplGlfwVulkan_NewFrame(); +IMGUI_API void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + +// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) +// Provided here if you want to chain callbacks. +// You can also handle inputs yourself and use those as a reference. +IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c); + diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp new file mode 100644 index 0000000..130fd87 --- /dev/null +++ b/examples/vulkan_example/main.cpp @@ -0,0 +1,539 @@ +// ImGui - standalone example application for Glfw + Vulkan, using programmable pipeline +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. + +#include + +#include // printf, fprintf +#include // abort +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include + +#include "imgui_impl_glfw_vulkan.h" + +#define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 + +static VkAllocationCallbacks* g_Allocator = NULL; +static VkInstance g_Instance = VK_NULL_HANDLE; +static VkSurfaceKHR g_Surface = VK_NULL_HANDLE; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static uint32_t g_QueueFamily = 0; +static VkQueue g_Queue = VK_NULL_HANDLE; + +static VkFormat g_Format = VK_FORMAT_B8G8R8A8_UNORM; +static VkColorSpaceKHR g_ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; +static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; + +static int fb_width, fb_height; +static uint32_t g_BackBufferIndex = 0; +static uint32_t g_BackBufferCount = 0; +static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; + +static uint32_t g_FrameIndex = 0; +static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; +static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; +static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; +static VkSemaphore g_Semaphore[IMGUI_VK_QUEUED_FRAMES]; + +static VkClearValue g_ClearValue = {}; + +static void check_vk_result(VkResult err) +{ + if (err == 0) return; + printf("VkResult %d\n", err); + if (err < 0) + abort(); +} + +static void resize_vulkan(GLFWwindow* /*window*/, int w, int h) +{ + VkResult err; + VkSwapchainKHR old_swapchain = g_Swapchain; + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + + // Destroy old Framebuffer: + for (uint32_t i=0; iAddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + + // Upload Fonts + { + VkResult err; + err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + check_vk_result(err); + VkCommandBufferBeginInfo begin_info = {}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info); + check_vk_result(err); + + ImGui_ImplGlfwVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); + + VkSubmitInfo end_info = {}; + end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + end_info.commandBufferCount = 1; + end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; + err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + check_vk_result(err); + err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); + check_vk_result(err); + + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + } + + bool show_test_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImColor(114, 144, 154); + + // Main loop + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + ImGui_ImplGlfwVulkan_NewFrame(); + + // 1. Show a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + { + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::ColorEdit3("clear color", (float*)&clear_color); + if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) + { + ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); + ImGui::ShowTestWindow(&show_test_window); + } + + g_ClearValue.color.float32[0] = clear_color.x; + g_ClearValue.color.float32[1] = clear_color.y; + g_ClearValue.color.float32[2] = clear_color.z; + g_ClearValue.color.float32[3] = clear_color.w; + + frame_begin(); + ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); + frame_end(); + } + + // Cleanup + VkResult err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_Shutdown(); + cleanup_vulkan(); + glfwTerminate(); + + return 0; +} diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp new file mode 100644 index 0000000..33d8e99 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -0,0 +1,935 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// GLFW +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include +#ifdef _WIN32 +#undef APIENTRY +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "imgui_impl_glfw_vulkan.h" + +// GLFW Data +static GLFWwindow* g_Window = NULL; +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; + +// Vulkan Data +static VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; + +static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; +static size_t g_BufferMemoryAlignment = 256; +static VkPipelineCreateFlags g_PipelineCreateFlags = 0; +static int g_FrameIndex = 0; + +static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; +static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; +static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; +static VkPipeline g_Pipeline = VK_NULL_HANDLE; + +static VkSampler g_FontSampler = VK_NULL_HANDLE; +static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; +static VkImage g_FontImage = VK_NULL_HANDLE; +static VkImageView g_FontView = VK_NULL_HANDLE; + +static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; + +static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; +static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; + +static unsigned char __glsl_shader_vert_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, + 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x41, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x06, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7f, 0x02, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x7f, 0x02, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x2e, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x60, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x41, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0xaa, 0x26, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xaa, 0x26, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x91, 0x02, 0x00, 0x00, + 0xea, 0x50, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xea, 0x50, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0xa1, 0x41, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x84, 0x36, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xa1, 0x41, 0x00, 0x00, 0x84, 0x36, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0x17, 0x2f, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_vert_spv_len = 1172; + +static unsigned char __glsl_shader_frag_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x7a, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x04, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x03, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x5d, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x0b, 0x40, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x90, 0x02, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x35, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x57, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xb9, 0x46, 0x00, 0x00, + 0xc0, 0x36, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0xe4, 0x23, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x00, + 0xb9, 0x46, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x0c, 0x00, 0x00, + 0xe4, 0x23, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_frag_spv_len = 660; + +static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<TotalVtxCount * sizeof(ImDrawVert); + if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) + { + if (g_VertexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); + if (g_VertexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); + size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; + } + + // Create the Index Buffer: + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) + { + if (g_IndexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); + if (g_IndexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); + size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = index_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_IndexBufferSize[g_FrameIndex] = index_buffer_size; + } + + // Upload Vertex and index Data: + { + ImDrawVert* vtx_dst; + ImDrawIdx* idx_dst; + err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].size = vertex_size; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].size = index_size; + err = vkFlushMappedMemoryRanges(g_Device, 2, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + } + + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = {g_DescriptorSet}; + vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; + VkDeviceSize vertex_offset[1] = {0}; + vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + } + + // Setup scale and translation: + { + float scale[2]; + scale[0] = 2.0f/io.DisplaySize.x; + scale[1] = 2.0f/io.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f; + translate[1] = -1.0f; + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + VkRect2D scissor; + scissor.offset.x = static_cast(pcmd->ClipRect.x); + scissor.offset.y = static_cast(pcmd->ClipRect.y); + scissor.extent.width = static_cast(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = static_cast(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? + vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +static const char* ImGui_ImplGlfwVulkan_GetClipboardText() +{ + return glfwGetClipboardString(g_Window); +} + +static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) +{ + glfwSetClipboardString(g_Window, text); +} + +void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +{ + if (action == GLFW_PRESS && button >= 0 && button < 3) + g_MousePressed[button] = true; +} + +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +{ + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. +} + +void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +} + +void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +{ + ImGuiIO& io = ImGui::GetIO(); + if (c > 0 && c < 0x10000) + io.AddInputCharacter((unsigned short)c); +} + +bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) +{ + ImGuiIO& io = ImGui::GetIO(); + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width*height*4*sizeof(char); + + VkResult err; + + // Create the Image: + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.extent.width = width; + info.extent.height = height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetImageMemoryRequirements(g_Device, g_FontImage, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create the Image View: + { + VkResult err; + VkImageViewCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.image = g_FontImage; + info.viewType = VK_IMAGE_VIEW_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.levelCount = 1; + info.subresourceRange.layerCount = 1; + err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Update the Descriptor Set: + { + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = g_FontSampler; + desc_image[0].imageView = g_FontView; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = g_DescriptorSet; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL); + } + + // Create the Upload Buffer: + { + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Upload to Buffer: + { + char* map = NULL; + err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); + ImGui_ImplGlfwVulkan_VkResult(err); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_UploadBufferMemory; + range[0].size = upload_size; + err = vkFlushMappedMemoryRanges(g_Device, 1, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_UploadBufferMemory); + } + // Copy to Image: + { + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = g_FontImage; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = g_FontImage; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); + } + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontImage; + + return true; +} + +bool ImGui_ImplGlfwVulkan_CreateDeviceObjects() +{ + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = __glsl_shader_vert_spv_len; + vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module); + ImGui_ImplGlfwVulkan_VkResult(err); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = __glsl_shader_frag_spv_len; + frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_PipelineLayout) + { + VkPushConstantRange push_constants[2] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 2; + push_constants[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[1].offset = sizeof(float) * 2; + push_constants[1].size = sizeof(float) * 2; + VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 2; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.dynamicStateCount = 2; + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = g_PipelineCreateFlags; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = g_PipelineLayout; + info.renderPass = g_RenderPass; + err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline); + ImGui_ImplGlfwVulkan_VkResult(err); + + vkDestroyShaderModule(g_Device, vert_module, g_Allocator); + vkDestroyShaderModule(g_Device, frag_module, g_Allocator); + + return true; +} + +void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects() +{ + if (g_UploadBuffer) + { + vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator); + g_UploadBuffer = VK_NULL_HANDLE; + } + if (g_UploadBufferMemory) + { + vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator); + g_UploadBufferMemory = VK_NULL_HANDLE; + } +} + +void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() +{ + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + for (int i=0; iallocator; + g_Gpu = init_data->gpu; + g_Device = init_data->device; + g_RenderPass = init_data->render_pass; + g_PipelineCache = init_data->pipeline_cache; + g_DescriptorPool = init_data->descriptor_pool; + g_CheckVkResult = init_data->check_vk_result; + + g_Window = window; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; +#ifdef _WIN32 + io.ImeWindowHandle = glfwGetWin32Window(g_Window); +#endif + + if (install_callbacks) + { + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); + } + + ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplGlfwVulkan_Shutdown() +{ + ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplGlfwVulkan_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + glfwGetWindowSize(g_Window, &w, &h); + glfwGetFramebufferSize(g_Window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + double current_time = glfwGetTime(); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } + else + { + io.MousePos = ImVec2(-1,-1); + } + + for (int i = 0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MousePressed[i] = false; + } + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + + // Start the frame + ImGui::NewFrame(); +} +void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) +{ + g_CommandBuffer = command_buffer; + ImGui::Render(); + g_CommandBuffer = VK_NULL_HANDLE; + g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h new file mode 100644 index 0000000..74d35a2 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -0,0 +1,40 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct GLFWwindow; + +#define IMGUI_VK_QUEUED_FRAMES 2 + +struct ImGui_ImplGlfwVulkan_Init_Data +{ + VkAllocationCallbacks* allocator; + VkPhysicalDevice gpu; + VkDevice device; + VkRenderPass render_pass; + VkPipelineCache pipeline_cache; + VkDescriptorPool descriptor_pool; + void (*check_vk_result)(VkResult err); +}; + +IMGUI_API bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data); +IMGUI_API void ImGui_ImplGlfwVulkan_Shutdown(); +IMGUI_API void ImGui_ImplGlfwVulkan_NewFrame(); +IMGUI_API void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + +// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) +// Provided here if you want to chain callbacks. +// You can also handle inputs yourself and use those as a reference. +IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c); + diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp new file mode 100644 index 0000000..130fd87 --- /dev/null +++ b/examples/vulkan_example/main.cpp @@ -0,0 +1,539 @@ +// ImGui - standalone example application for Glfw + Vulkan, using programmable pipeline +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. + +#include + +#include // printf, fprintf +#include // abort +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include + +#include "imgui_impl_glfw_vulkan.h" + +#define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 + +static VkAllocationCallbacks* g_Allocator = NULL; +static VkInstance g_Instance = VK_NULL_HANDLE; +static VkSurfaceKHR g_Surface = VK_NULL_HANDLE; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static uint32_t g_QueueFamily = 0; +static VkQueue g_Queue = VK_NULL_HANDLE; + +static VkFormat g_Format = VK_FORMAT_B8G8R8A8_UNORM; +static VkColorSpaceKHR g_ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; +static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; + +static int fb_width, fb_height; +static uint32_t g_BackBufferIndex = 0; +static uint32_t g_BackBufferCount = 0; +static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; + +static uint32_t g_FrameIndex = 0; +static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; +static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; +static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; +static VkSemaphore g_Semaphore[IMGUI_VK_QUEUED_FRAMES]; + +static VkClearValue g_ClearValue = {}; + +static void check_vk_result(VkResult err) +{ + if (err == 0) return; + printf("VkResult %d\n", err); + if (err < 0) + abort(); +} + +static void resize_vulkan(GLFWwindow* /*window*/, int w, int h) +{ + VkResult err; + VkSwapchainKHR old_swapchain = g_Swapchain; + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + + // Destroy old Framebuffer: + for (uint32_t i=0; iAddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + + // Upload Fonts + { + VkResult err; + err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + check_vk_result(err); + VkCommandBufferBeginInfo begin_info = {}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info); + check_vk_result(err); + + ImGui_ImplGlfwVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); + + VkSubmitInfo end_info = {}; + end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + end_info.commandBufferCount = 1; + end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; + err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + check_vk_result(err); + err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); + check_vk_result(err); + + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + } + + bool show_test_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImColor(114, 144, 154); + + // Main loop + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + ImGui_ImplGlfwVulkan_NewFrame(); + + // 1. Show a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + { + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::ColorEdit3("clear color", (float*)&clear_color); + if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) + { + ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); + ImGui::ShowTestWindow(&show_test_window); + } + + g_ClearValue.color.float32[0] = clear_color.x; + g_ClearValue.color.float32[1] = clear_color.y; + g_ClearValue.color.float32[2] = clear_color.z; + g_ClearValue.color.float32[3] = clear_color.w; + + frame_begin(); + ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); + frame_end(); + } + + // Cleanup + VkResult err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_Shutdown(); + cleanup_vulkan(); + glfwTerminate(); + + return 0; +} diff --git a/imgui.cpp b/imgui.cpp index 8f2b87f..316dea5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (main code and documentation) // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. @@ -152,6 +152,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). + - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - 2016/02/21 (1.48) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to ColorEdit*() functions @@ -506,6 +508,7 @@ - color: add a better color picker (#346) - node/graph editor (#306) - pie menus patterns (#434) + - drag'n drop, dragging helpers (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479) - plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals) - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots) - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value) @@ -694,13 +697,12 @@ WindowMinSize = ImVec2(32,32); // Minimum window size WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text - ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows + ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin() IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -715,8 +717,9 @@ Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input @@ -754,7 +757,6 @@ Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } @@ -1652,7 +1654,7 @@ { ImGuiState& g = *GImGui; IM_ASSERT(g.CurrentWindowStack.Size >= 2); - return g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; + return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) @@ -2339,9 +2341,9 @@ // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices) // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly. - IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. - IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= ((unsigned long long int)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. - + IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. + IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. + out_render_list.push_back(draw_list); GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; @@ -3139,9 +3141,8 @@ void ImGui::BeginTooltip() { - ImGuiState& g = *GImGui; ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; - ImGui::Begin("##Tooltip", NULL, ImVec2(0,0), g.Style.Colors[ImGuiCol_TooltipBg].w, flags); + ImGui::Begin("##Tooltip", NULL, flags); } void ImGui::EndTooltip() @@ -3279,9 +3280,8 @@ ImFormatString(name, 20, "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth else ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame - float alpha = 1.0f; - bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), alpha, flags); + bool opened = ImGui::Begin(name, NULL, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display) @@ -3312,7 +3312,7 @@ } ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; - bool opened = ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), -1.0f, flags); + bool opened = ImGui::Begin(name, p_opened, flags); if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) { ImGui::EndPopup(); @@ -3392,8 +3392,7 @@ char title[256]; ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id); - const float alpha = 1.0f; - bool ret = ImGui::Begin(title, NULL, size, alpha, flags); + bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; @@ -3443,13 +3442,14 @@ const ImGuiStyle& style = g.Style; ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); - return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove | extra_flags); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); } void ImGui::EndChildFrame() { ImGui::EndChild(); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); ImGui::PopStyleColor(); } @@ -3692,10 +3692,6 @@ window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. - // Default alpha - if (bg_alpha < 0.0f) - bg_alpha = style.WindowFillAlphaDefault; - // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { @@ -3767,7 +3763,7 @@ } // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects. - window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; + window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; // Calculate auto-fit size ImVec2 size_auto_fit; @@ -3981,27 +3977,26 @@ } // Scrollbars - window->ScrollbarY = (flags & ImGuiWindowFlags_ForceVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_ForceHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; // Window background - if (bg_alpha > 0.0f) - { - ImGuiCol col_idx; - if ((flags & ImGuiWindowFlags_ComboBox) != 0) - col_idx = ImGuiCol_ComboBg; - else if ((flags & ImGuiWindowFlags_Tooltip) != 0) - col_idx = ImGuiCol_TooltipBg; - else if ((flags & ImGuiWindowFlags_Popup) != 0) - col_idx = ImGuiCol_WindowBg; - else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) - col_idx = ImGuiCol_ChildWindowBg; - else - col_idx = ImGuiCol_WindowBg; - window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, GetColorU32(col_idx, bg_alpha), window_rounding); - } + // Default alpha + ImGuiCol bg_color_idx = ImGuiCol_WindowBg; + if ((flags & ImGuiWindowFlags_ComboBox) != 0) + bg_color_idx = ImGuiCol_ComboBg; + else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0) + bg_color_idx = ImGuiCol_PopupBg; + else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) + bg_color_idx = ImGuiCol_ChildWindowBg; + ImVec4 bg_color = style.Colors[bg_color_idx]; + if (bg_alpha >= 0.0f) + bg_color.w = bg_alpha; + bg_color.w *= style.Alpha; + if (bg_color.w > 0.0f) + window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding); // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) @@ -4521,6 +4516,7 @@ case ImGuiCol_TextDisabled: return "TextDisabled"; case ImGuiCol_WindowBg: return "WindowBg"; case ImGuiCol_ChildWindowBg: return "ChildWindowBg"; + case ImGuiCol_PopupBg: return "PopupBg"; case ImGuiCol_Border: return "Border"; case ImGuiCol_BorderShadow: return "BorderShadow"; case ImGuiCol_FrameBg: return "FrameBg"; @@ -4558,7 +4554,6 @@ case ImGuiCol_PlotHistogram: return "PlotHistogram"; case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; - case ImGuiCol_TooltipBg: return "TooltipBg"; case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; } IM_ASSERT(0); @@ -7104,9 +7099,9 @@ static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; } -static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } #ifdef __APPLE__ // FIXME: Move setting to IO structure +static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } #else static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } @@ -7310,7 +7305,6 @@ return false; } draw_window = GetCurrentWindow(); - draw_window->DC.CursorPos += style.FramePadding; size.x -= draw_window->ScrollbarSizes.x; } else @@ -8501,7 +8495,7 @@ bool want_open = false, want_close = false; if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { - // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers so menus feel more reactive. + // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; if (g.HoveredWindow == window && g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) { diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp new file mode 100644 index 0000000..33d8e99 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -0,0 +1,935 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// GLFW +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include +#ifdef _WIN32 +#undef APIENTRY +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "imgui_impl_glfw_vulkan.h" + +// GLFW Data +static GLFWwindow* g_Window = NULL; +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; + +// Vulkan Data +static VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; + +static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; +static size_t g_BufferMemoryAlignment = 256; +static VkPipelineCreateFlags g_PipelineCreateFlags = 0; +static int g_FrameIndex = 0; + +static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; +static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; +static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; +static VkPipeline g_Pipeline = VK_NULL_HANDLE; + +static VkSampler g_FontSampler = VK_NULL_HANDLE; +static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; +static VkImage g_FontImage = VK_NULL_HANDLE; +static VkImageView g_FontView = VK_NULL_HANDLE; + +static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; + +static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; +static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; + +static unsigned char __glsl_shader_vert_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, + 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x41, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x06, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7f, 0x02, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x7f, 0x02, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x2e, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x60, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x41, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0xaa, 0x26, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xaa, 0x26, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x91, 0x02, 0x00, 0x00, + 0xea, 0x50, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xea, 0x50, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0xa1, 0x41, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x84, 0x36, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xa1, 0x41, 0x00, 0x00, 0x84, 0x36, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0x17, 0x2f, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_vert_spv_len = 1172; + +static unsigned char __glsl_shader_frag_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x7a, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x04, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x03, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x5d, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x0b, 0x40, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x90, 0x02, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x35, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x57, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xb9, 0x46, 0x00, 0x00, + 0xc0, 0x36, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0xe4, 0x23, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x00, + 0xb9, 0x46, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x0c, 0x00, 0x00, + 0xe4, 0x23, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_frag_spv_len = 660; + +static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<TotalVtxCount * sizeof(ImDrawVert); + if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) + { + if (g_VertexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); + if (g_VertexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); + size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; + } + + // Create the Index Buffer: + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) + { + if (g_IndexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); + if (g_IndexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); + size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = index_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_IndexBufferSize[g_FrameIndex] = index_buffer_size; + } + + // Upload Vertex and index Data: + { + ImDrawVert* vtx_dst; + ImDrawIdx* idx_dst; + err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].size = vertex_size; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].size = index_size; + err = vkFlushMappedMemoryRanges(g_Device, 2, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + } + + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = {g_DescriptorSet}; + vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; + VkDeviceSize vertex_offset[1] = {0}; + vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + } + + // Setup scale and translation: + { + float scale[2]; + scale[0] = 2.0f/io.DisplaySize.x; + scale[1] = 2.0f/io.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f; + translate[1] = -1.0f; + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + VkRect2D scissor; + scissor.offset.x = static_cast(pcmd->ClipRect.x); + scissor.offset.y = static_cast(pcmd->ClipRect.y); + scissor.extent.width = static_cast(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = static_cast(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? + vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +static const char* ImGui_ImplGlfwVulkan_GetClipboardText() +{ + return glfwGetClipboardString(g_Window); +} + +static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) +{ + glfwSetClipboardString(g_Window, text); +} + +void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +{ + if (action == GLFW_PRESS && button >= 0 && button < 3) + g_MousePressed[button] = true; +} + +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +{ + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. +} + +void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +} + +void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +{ + ImGuiIO& io = ImGui::GetIO(); + if (c > 0 && c < 0x10000) + io.AddInputCharacter((unsigned short)c); +} + +bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) +{ + ImGuiIO& io = ImGui::GetIO(); + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width*height*4*sizeof(char); + + VkResult err; + + // Create the Image: + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.extent.width = width; + info.extent.height = height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetImageMemoryRequirements(g_Device, g_FontImage, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create the Image View: + { + VkResult err; + VkImageViewCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.image = g_FontImage; + info.viewType = VK_IMAGE_VIEW_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.levelCount = 1; + info.subresourceRange.layerCount = 1; + err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Update the Descriptor Set: + { + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = g_FontSampler; + desc_image[0].imageView = g_FontView; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = g_DescriptorSet; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL); + } + + // Create the Upload Buffer: + { + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Upload to Buffer: + { + char* map = NULL; + err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); + ImGui_ImplGlfwVulkan_VkResult(err); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_UploadBufferMemory; + range[0].size = upload_size; + err = vkFlushMappedMemoryRanges(g_Device, 1, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_UploadBufferMemory); + } + // Copy to Image: + { + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = g_FontImage; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = g_FontImage; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); + } + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontImage; + + return true; +} + +bool ImGui_ImplGlfwVulkan_CreateDeviceObjects() +{ + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = __glsl_shader_vert_spv_len; + vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module); + ImGui_ImplGlfwVulkan_VkResult(err); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = __glsl_shader_frag_spv_len; + frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_PipelineLayout) + { + VkPushConstantRange push_constants[2] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 2; + push_constants[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[1].offset = sizeof(float) * 2; + push_constants[1].size = sizeof(float) * 2; + VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 2; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.dynamicStateCount = 2; + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = g_PipelineCreateFlags; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = g_PipelineLayout; + info.renderPass = g_RenderPass; + err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline); + ImGui_ImplGlfwVulkan_VkResult(err); + + vkDestroyShaderModule(g_Device, vert_module, g_Allocator); + vkDestroyShaderModule(g_Device, frag_module, g_Allocator); + + return true; +} + +void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects() +{ + if (g_UploadBuffer) + { + vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator); + g_UploadBuffer = VK_NULL_HANDLE; + } + if (g_UploadBufferMemory) + { + vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator); + g_UploadBufferMemory = VK_NULL_HANDLE; + } +} + +void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() +{ + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + for (int i=0; iallocator; + g_Gpu = init_data->gpu; + g_Device = init_data->device; + g_RenderPass = init_data->render_pass; + g_PipelineCache = init_data->pipeline_cache; + g_DescriptorPool = init_data->descriptor_pool; + g_CheckVkResult = init_data->check_vk_result; + + g_Window = window; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; +#ifdef _WIN32 + io.ImeWindowHandle = glfwGetWin32Window(g_Window); +#endif + + if (install_callbacks) + { + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); + } + + ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplGlfwVulkan_Shutdown() +{ + ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplGlfwVulkan_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + glfwGetWindowSize(g_Window, &w, &h); + glfwGetFramebufferSize(g_Window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + double current_time = glfwGetTime(); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } + else + { + io.MousePos = ImVec2(-1,-1); + } + + for (int i = 0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MousePressed[i] = false; + } + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + + // Start the frame + ImGui::NewFrame(); +} +void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) +{ + g_CommandBuffer = command_buffer; + ImGui::Render(); + g_CommandBuffer = VK_NULL_HANDLE; + g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h new file mode 100644 index 0000000..74d35a2 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -0,0 +1,40 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct GLFWwindow; + +#define IMGUI_VK_QUEUED_FRAMES 2 + +struct ImGui_ImplGlfwVulkan_Init_Data +{ + VkAllocationCallbacks* allocator; + VkPhysicalDevice gpu; + VkDevice device; + VkRenderPass render_pass; + VkPipelineCache pipeline_cache; + VkDescriptorPool descriptor_pool; + void (*check_vk_result)(VkResult err); +}; + +IMGUI_API bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data); +IMGUI_API void ImGui_ImplGlfwVulkan_Shutdown(); +IMGUI_API void ImGui_ImplGlfwVulkan_NewFrame(); +IMGUI_API void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + +// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) +// Provided here if you want to chain callbacks. +// You can also handle inputs yourself and use those as a reference. +IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c); + diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp new file mode 100644 index 0000000..130fd87 --- /dev/null +++ b/examples/vulkan_example/main.cpp @@ -0,0 +1,539 @@ +// ImGui - standalone example application for Glfw + Vulkan, using programmable pipeline +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. + +#include + +#include // printf, fprintf +#include // abort +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include + +#include "imgui_impl_glfw_vulkan.h" + +#define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 + +static VkAllocationCallbacks* g_Allocator = NULL; +static VkInstance g_Instance = VK_NULL_HANDLE; +static VkSurfaceKHR g_Surface = VK_NULL_HANDLE; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static uint32_t g_QueueFamily = 0; +static VkQueue g_Queue = VK_NULL_HANDLE; + +static VkFormat g_Format = VK_FORMAT_B8G8R8A8_UNORM; +static VkColorSpaceKHR g_ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; +static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; + +static int fb_width, fb_height; +static uint32_t g_BackBufferIndex = 0; +static uint32_t g_BackBufferCount = 0; +static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; + +static uint32_t g_FrameIndex = 0; +static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; +static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; +static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; +static VkSemaphore g_Semaphore[IMGUI_VK_QUEUED_FRAMES]; + +static VkClearValue g_ClearValue = {}; + +static void check_vk_result(VkResult err) +{ + if (err == 0) return; + printf("VkResult %d\n", err); + if (err < 0) + abort(); +} + +static void resize_vulkan(GLFWwindow* /*window*/, int w, int h) +{ + VkResult err; + VkSwapchainKHR old_swapchain = g_Swapchain; + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + + // Destroy old Framebuffer: + for (uint32_t i=0; iAddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + + // Upload Fonts + { + VkResult err; + err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + check_vk_result(err); + VkCommandBufferBeginInfo begin_info = {}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info); + check_vk_result(err); + + ImGui_ImplGlfwVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); + + VkSubmitInfo end_info = {}; + end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + end_info.commandBufferCount = 1; + end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; + err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + check_vk_result(err); + err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); + check_vk_result(err); + + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + } + + bool show_test_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImColor(114, 144, 154); + + // Main loop + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + ImGui_ImplGlfwVulkan_NewFrame(); + + // 1. Show a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + { + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::ColorEdit3("clear color", (float*)&clear_color); + if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) + { + ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); + ImGui::ShowTestWindow(&show_test_window); + } + + g_ClearValue.color.float32[0] = clear_color.x; + g_ClearValue.color.float32[1] = clear_color.y; + g_ClearValue.color.float32[2] = clear_color.z; + g_ClearValue.color.float32[3] = clear_color.w; + + frame_begin(); + ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); + frame_end(); + } + + // Cleanup + VkResult err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_Shutdown(); + cleanup_vulkan(); + glfwTerminate(); + + return 0; +} diff --git a/imgui.cpp b/imgui.cpp index 8f2b87f..316dea5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (main code and documentation) // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. @@ -152,6 +152,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). + - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - 2016/02/21 (1.48) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to ColorEdit*() functions @@ -506,6 +508,7 @@ - color: add a better color picker (#346) - node/graph editor (#306) - pie menus patterns (#434) + - drag'n drop, dragging helpers (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479) - plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals) - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots) - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value) @@ -694,13 +697,12 @@ WindowMinSize = ImVec2(32,32); // Minimum window size WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text - ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows + ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin() IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -715,8 +717,9 @@ Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input @@ -754,7 +757,6 @@ Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } @@ -1652,7 +1654,7 @@ { ImGuiState& g = *GImGui; IM_ASSERT(g.CurrentWindowStack.Size >= 2); - return g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; + return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) @@ -2339,9 +2341,9 @@ // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices) // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly. - IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. - IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= ((unsigned long long int)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. - + IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. + IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. + out_render_list.push_back(draw_list); GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; @@ -3139,9 +3141,8 @@ void ImGui::BeginTooltip() { - ImGuiState& g = *GImGui; ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; - ImGui::Begin("##Tooltip", NULL, ImVec2(0,0), g.Style.Colors[ImGuiCol_TooltipBg].w, flags); + ImGui::Begin("##Tooltip", NULL, flags); } void ImGui::EndTooltip() @@ -3279,9 +3280,8 @@ ImFormatString(name, 20, "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth else ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame - float alpha = 1.0f; - bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), alpha, flags); + bool opened = ImGui::Begin(name, NULL, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display) @@ -3312,7 +3312,7 @@ } ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; - bool opened = ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), -1.0f, flags); + bool opened = ImGui::Begin(name, p_opened, flags); if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) { ImGui::EndPopup(); @@ -3392,8 +3392,7 @@ char title[256]; ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id); - const float alpha = 1.0f; - bool ret = ImGui::Begin(title, NULL, size, alpha, flags); + bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; @@ -3443,13 +3442,14 @@ const ImGuiStyle& style = g.Style; ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); - return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove | extra_flags); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); } void ImGui::EndChildFrame() { ImGui::EndChild(); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); ImGui::PopStyleColor(); } @@ -3692,10 +3692,6 @@ window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. - // Default alpha - if (bg_alpha < 0.0f) - bg_alpha = style.WindowFillAlphaDefault; - // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { @@ -3767,7 +3763,7 @@ } // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects. - window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; + window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; // Calculate auto-fit size ImVec2 size_auto_fit; @@ -3981,27 +3977,26 @@ } // Scrollbars - window->ScrollbarY = (flags & ImGuiWindowFlags_ForceVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_ForceHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; // Window background - if (bg_alpha > 0.0f) - { - ImGuiCol col_idx; - if ((flags & ImGuiWindowFlags_ComboBox) != 0) - col_idx = ImGuiCol_ComboBg; - else if ((flags & ImGuiWindowFlags_Tooltip) != 0) - col_idx = ImGuiCol_TooltipBg; - else if ((flags & ImGuiWindowFlags_Popup) != 0) - col_idx = ImGuiCol_WindowBg; - else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) - col_idx = ImGuiCol_ChildWindowBg; - else - col_idx = ImGuiCol_WindowBg; - window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, GetColorU32(col_idx, bg_alpha), window_rounding); - } + // Default alpha + ImGuiCol bg_color_idx = ImGuiCol_WindowBg; + if ((flags & ImGuiWindowFlags_ComboBox) != 0) + bg_color_idx = ImGuiCol_ComboBg; + else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0) + bg_color_idx = ImGuiCol_PopupBg; + else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) + bg_color_idx = ImGuiCol_ChildWindowBg; + ImVec4 bg_color = style.Colors[bg_color_idx]; + if (bg_alpha >= 0.0f) + bg_color.w = bg_alpha; + bg_color.w *= style.Alpha; + if (bg_color.w > 0.0f) + window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding); // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) @@ -4521,6 +4516,7 @@ case ImGuiCol_TextDisabled: return "TextDisabled"; case ImGuiCol_WindowBg: return "WindowBg"; case ImGuiCol_ChildWindowBg: return "ChildWindowBg"; + case ImGuiCol_PopupBg: return "PopupBg"; case ImGuiCol_Border: return "Border"; case ImGuiCol_BorderShadow: return "BorderShadow"; case ImGuiCol_FrameBg: return "FrameBg"; @@ -4558,7 +4554,6 @@ case ImGuiCol_PlotHistogram: return "PlotHistogram"; case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; - case ImGuiCol_TooltipBg: return "TooltipBg"; case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; } IM_ASSERT(0); @@ -7104,9 +7099,9 @@ static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; } -static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } #ifdef __APPLE__ // FIXME: Move setting to IO structure +static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } #else static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } @@ -7310,7 +7305,6 @@ return false; } draw_window = GetCurrentWindow(); - draw_window->DC.CursorPos += style.FramePadding; size.x -= draw_window->ScrollbarSizes.x; } else @@ -8501,7 +8495,7 @@ bool want_open = false, want_close = false; if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { - // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers so menus feel more reactive. + // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; if (g.HoveredWindow == window && g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) { diff --git a/imgui.h b/imgui.h index c7eaa1b..3641824 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.48 WIP" +#define IMGUI_VERSION "1.49 WIP" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API @@ -114,7 +114,7 @@ // Window IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // ". this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. + IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. IMGUI_API void End(); // finish appending to current window, pop it off the window stack. IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " @@ -316,7 +316,7 @@ IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); - IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node to be opened. + IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened. // Widgets: Selectable / Lists IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height @@ -467,11 +467,12 @@ ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar - ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You need to use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. + ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) - ImGuiWindowFlags_ForceVerticalScrollbar = 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) - ImGuiWindowFlags_ForceHorizontalScrollbar=1 << 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) + ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() @@ -546,8 +547,9 @@ { ImGuiCol_Text, ImGuiCol_TextDisabled, - ImGuiCol_WindowBg, - ImGuiCol_ChildWindowBg, + ImGuiCol_WindowBg, // Background of normal windows + ImGuiCol_ChildWindowBg, // Background of child windows + ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows ImGuiCol_Border, ImGuiCol_BorderShadow, ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input @@ -585,7 +587,6 @@ ImGuiCol_PlotHistogram, ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, - ImGuiCol_TooltipBg, ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active ImGuiCol_COUNT }; @@ -667,7 +668,6 @@ ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - float WindowFillAlphaDefault; // Default alpha of window background, if not specified in ImGui::Begin() float IndentSpacing; // Horizontal indentation when e.g. entering a tree node float ColumnsMinSpacing; // Minimum horizontal spacing between two columns float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -895,6 +895,7 @@ int CountGrep; ImGuiTextFilter(const char* default_filter = ""); + ~ImGuiTextFilter() {} void Clear() { InputBuf[0] = 0; Build(); } bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build bool PassFilter(const char* text, const char* text_end = NULL) const; @@ -1157,7 +1158,7 @@ // Stateful path API, add points then finish with PathFill() or PathStroke() inline void PathClear() { _Path.resize(0); } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } - inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || _Path[_Path.Size-1].x != pos.x || _Path[_Path.Size-1].y != pos.y) _Path.push_back(pos); } + inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp new file mode 100644 index 0000000..33d8e99 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -0,0 +1,935 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// GLFW +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include +#ifdef _WIN32 +#undef APIENTRY +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "imgui_impl_glfw_vulkan.h" + +// GLFW Data +static GLFWwindow* g_Window = NULL; +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; + +// Vulkan Data +static VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; + +static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; +static size_t g_BufferMemoryAlignment = 256; +static VkPipelineCreateFlags g_PipelineCreateFlags = 0; +static int g_FrameIndex = 0; + +static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; +static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; +static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; +static VkPipeline g_Pipeline = VK_NULL_HANDLE; + +static VkSampler g_FontSampler = VK_NULL_HANDLE; +static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; +static VkImage g_FontImage = VK_NULL_HANDLE; +static VkImageView g_FontView = VK_NULL_HANDLE; + +static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; + +static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; +static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; + +static unsigned char __glsl_shader_vert_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, + 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x41, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x06, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7f, 0x02, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x7f, 0x02, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x2e, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x60, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x41, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0xaa, 0x26, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xaa, 0x26, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x91, 0x02, 0x00, 0x00, + 0xea, 0x50, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xea, 0x50, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0xa1, 0x41, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x84, 0x36, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xa1, 0x41, 0x00, 0x00, 0x84, 0x36, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0x17, 0x2f, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_vert_spv_len = 1172; + +static unsigned char __glsl_shader_frag_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x7a, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x04, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x03, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x5d, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x0b, 0x40, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x90, 0x02, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x35, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x57, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xb9, 0x46, 0x00, 0x00, + 0xc0, 0x36, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0xe4, 0x23, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x00, + 0xb9, 0x46, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x0c, 0x00, 0x00, + 0xe4, 0x23, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_frag_spv_len = 660; + +static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<TotalVtxCount * sizeof(ImDrawVert); + if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) + { + if (g_VertexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); + if (g_VertexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); + size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; + } + + // Create the Index Buffer: + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) + { + if (g_IndexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); + if (g_IndexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); + size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = index_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_IndexBufferSize[g_FrameIndex] = index_buffer_size; + } + + // Upload Vertex and index Data: + { + ImDrawVert* vtx_dst; + ImDrawIdx* idx_dst; + err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].size = vertex_size; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].size = index_size; + err = vkFlushMappedMemoryRanges(g_Device, 2, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + } + + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = {g_DescriptorSet}; + vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; + VkDeviceSize vertex_offset[1] = {0}; + vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + } + + // Setup scale and translation: + { + float scale[2]; + scale[0] = 2.0f/io.DisplaySize.x; + scale[1] = 2.0f/io.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f; + translate[1] = -1.0f; + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + VkRect2D scissor; + scissor.offset.x = static_cast(pcmd->ClipRect.x); + scissor.offset.y = static_cast(pcmd->ClipRect.y); + scissor.extent.width = static_cast(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = static_cast(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? + vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +static const char* ImGui_ImplGlfwVulkan_GetClipboardText() +{ + return glfwGetClipboardString(g_Window); +} + +static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) +{ + glfwSetClipboardString(g_Window, text); +} + +void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +{ + if (action == GLFW_PRESS && button >= 0 && button < 3) + g_MousePressed[button] = true; +} + +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +{ + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. +} + +void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +} + +void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +{ + ImGuiIO& io = ImGui::GetIO(); + if (c > 0 && c < 0x10000) + io.AddInputCharacter((unsigned short)c); +} + +bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) +{ + ImGuiIO& io = ImGui::GetIO(); + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width*height*4*sizeof(char); + + VkResult err; + + // Create the Image: + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.extent.width = width; + info.extent.height = height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetImageMemoryRequirements(g_Device, g_FontImage, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create the Image View: + { + VkResult err; + VkImageViewCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.image = g_FontImage; + info.viewType = VK_IMAGE_VIEW_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.levelCount = 1; + info.subresourceRange.layerCount = 1; + err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Update the Descriptor Set: + { + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = g_FontSampler; + desc_image[0].imageView = g_FontView; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = g_DescriptorSet; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL); + } + + // Create the Upload Buffer: + { + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Upload to Buffer: + { + char* map = NULL; + err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); + ImGui_ImplGlfwVulkan_VkResult(err); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_UploadBufferMemory; + range[0].size = upload_size; + err = vkFlushMappedMemoryRanges(g_Device, 1, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_UploadBufferMemory); + } + // Copy to Image: + { + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = g_FontImage; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = g_FontImage; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); + } + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontImage; + + return true; +} + +bool ImGui_ImplGlfwVulkan_CreateDeviceObjects() +{ + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = __glsl_shader_vert_spv_len; + vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module); + ImGui_ImplGlfwVulkan_VkResult(err); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = __glsl_shader_frag_spv_len; + frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_PipelineLayout) + { + VkPushConstantRange push_constants[2] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 2; + push_constants[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[1].offset = sizeof(float) * 2; + push_constants[1].size = sizeof(float) * 2; + VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 2; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.dynamicStateCount = 2; + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = g_PipelineCreateFlags; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = g_PipelineLayout; + info.renderPass = g_RenderPass; + err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline); + ImGui_ImplGlfwVulkan_VkResult(err); + + vkDestroyShaderModule(g_Device, vert_module, g_Allocator); + vkDestroyShaderModule(g_Device, frag_module, g_Allocator); + + return true; +} + +void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects() +{ + if (g_UploadBuffer) + { + vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator); + g_UploadBuffer = VK_NULL_HANDLE; + } + if (g_UploadBufferMemory) + { + vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator); + g_UploadBufferMemory = VK_NULL_HANDLE; + } +} + +void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() +{ + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + for (int i=0; iallocator; + g_Gpu = init_data->gpu; + g_Device = init_data->device; + g_RenderPass = init_data->render_pass; + g_PipelineCache = init_data->pipeline_cache; + g_DescriptorPool = init_data->descriptor_pool; + g_CheckVkResult = init_data->check_vk_result; + + g_Window = window; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; +#ifdef _WIN32 + io.ImeWindowHandle = glfwGetWin32Window(g_Window); +#endif + + if (install_callbacks) + { + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); + } + + ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplGlfwVulkan_Shutdown() +{ + ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplGlfwVulkan_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + glfwGetWindowSize(g_Window, &w, &h); + glfwGetFramebufferSize(g_Window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + double current_time = glfwGetTime(); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } + else + { + io.MousePos = ImVec2(-1,-1); + } + + for (int i = 0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MousePressed[i] = false; + } + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + + // Start the frame + ImGui::NewFrame(); +} +void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) +{ + g_CommandBuffer = command_buffer; + ImGui::Render(); + g_CommandBuffer = VK_NULL_HANDLE; + g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h new file mode 100644 index 0000000..74d35a2 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -0,0 +1,40 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct GLFWwindow; + +#define IMGUI_VK_QUEUED_FRAMES 2 + +struct ImGui_ImplGlfwVulkan_Init_Data +{ + VkAllocationCallbacks* allocator; + VkPhysicalDevice gpu; + VkDevice device; + VkRenderPass render_pass; + VkPipelineCache pipeline_cache; + VkDescriptorPool descriptor_pool; + void (*check_vk_result)(VkResult err); +}; + +IMGUI_API bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data); +IMGUI_API void ImGui_ImplGlfwVulkan_Shutdown(); +IMGUI_API void ImGui_ImplGlfwVulkan_NewFrame(); +IMGUI_API void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + +// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) +// Provided here if you want to chain callbacks. +// You can also handle inputs yourself and use those as a reference. +IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c); + diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp new file mode 100644 index 0000000..130fd87 --- /dev/null +++ b/examples/vulkan_example/main.cpp @@ -0,0 +1,539 @@ +// ImGui - standalone example application for Glfw + Vulkan, using programmable pipeline +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. + +#include + +#include // printf, fprintf +#include // abort +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include + +#include "imgui_impl_glfw_vulkan.h" + +#define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 + +static VkAllocationCallbacks* g_Allocator = NULL; +static VkInstance g_Instance = VK_NULL_HANDLE; +static VkSurfaceKHR g_Surface = VK_NULL_HANDLE; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static uint32_t g_QueueFamily = 0; +static VkQueue g_Queue = VK_NULL_HANDLE; + +static VkFormat g_Format = VK_FORMAT_B8G8R8A8_UNORM; +static VkColorSpaceKHR g_ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; +static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; + +static int fb_width, fb_height; +static uint32_t g_BackBufferIndex = 0; +static uint32_t g_BackBufferCount = 0; +static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; + +static uint32_t g_FrameIndex = 0; +static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; +static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; +static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; +static VkSemaphore g_Semaphore[IMGUI_VK_QUEUED_FRAMES]; + +static VkClearValue g_ClearValue = {}; + +static void check_vk_result(VkResult err) +{ + if (err == 0) return; + printf("VkResult %d\n", err); + if (err < 0) + abort(); +} + +static void resize_vulkan(GLFWwindow* /*window*/, int w, int h) +{ + VkResult err; + VkSwapchainKHR old_swapchain = g_Swapchain; + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + + // Destroy old Framebuffer: + for (uint32_t i=0; iAddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + + // Upload Fonts + { + VkResult err; + err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + check_vk_result(err); + VkCommandBufferBeginInfo begin_info = {}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info); + check_vk_result(err); + + ImGui_ImplGlfwVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); + + VkSubmitInfo end_info = {}; + end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + end_info.commandBufferCount = 1; + end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; + err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + check_vk_result(err); + err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); + check_vk_result(err); + + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + } + + bool show_test_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImColor(114, 144, 154); + + // Main loop + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + ImGui_ImplGlfwVulkan_NewFrame(); + + // 1. Show a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + { + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::ColorEdit3("clear color", (float*)&clear_color); + if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) + { + ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); + ImGui::ShowTestWindow(&show_test_window); + } + + g_ClearValue.color.float32[0] = clear_color.x; + g_ClearValue.color.float32[1] = clear_color.y; + g_ClearValue.color.float32[2] = clear_color.z; + g_ClearValue.color.float32[3] = clear_color.w; + + frame_begin(); + ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); + frame_end(); + } + + // Cleanup + VkResult err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_Shutdown(); + cleanup_vulkan(); + glfwTerminate(); + + return 0; +} diff --git a/imgui.cpp b/imgui.cpp index 8f2b87f..316dea5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (main code and documentation) // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. @@ -152,6 +152,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). + - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - 2016/02/21 (1.48) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to ColorEdit*() functions @@ -506,6 +508,7 @@ - color: add a better color picker (#346) - node/graph editor (#306) - pie menus patterns (#434) + - drag'n drop, dragging helpers (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479) - plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals) - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots) - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value) @@ -694,13 +697,12 @@ WindowMinSize = ImVec2(32,32); // Minimum window size WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text - ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows + ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin() IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -715,8 +717,9 @@ Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input @@ -754,7 +757,6 @@ Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } @@ -1652,7 +1654,7 @@ { ImGuiState& g = *GImGui; IM_ASSERT(g.CurrentWindowStack.Size >= 2); - return g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; + return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) @@ -2339,9 +2341,9 @@ // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices) // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly. - IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. - IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= ((unsigned long long int)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. - + IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. + IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. + out_render_list.push_back(draw_list); GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; @@ -3139,9 +3141,8 @@ void ImGui::BeginTooltip() { - ImGuiState& g = *GImGui; ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; - ImGui::Begin("##Tooltip", NULL, ImVec2(0,0), g.Style.Colors[ImGuiCol_TooltipBg].w, flags); + ImGui::Begin("##Tooltip", NULL, flags); } void ImGui::EndTooltip() @@ -3279,9 +3280,8 @@ ImFormatString(name, 20, "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth else ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame - float alpha = 1.0f; - bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), alpha, flags); + bool opened = ImGui::Begin(name, NULL, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display) @@ -3312,7 +3312,7 @@ } ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; - bool opened = ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), -1.0f, flags); + bool opened = ImGui::Begin(name, p_opened, flags); if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) { ImGui::EndPopup(); @@ -3392,8 +3392,7 @@ char title[256]; ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id); - const float alpha = 1.0f; - bool ret = ImGui::Begin(title, NULL, size, alpha, flags); + bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; @@ -3443,13 +3442,14 @@ const ImGuiStyle& style = g.Style; ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); - return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove | extra_flags); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); } void ImGui::EndChildFrame() { ImGui::EndChild(); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); ImGui::PopStyleColor(); } @@ -3692,10 +3692,6 @@ window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. - // Default alpha - if (bg_alpha < 0.0f) - bg_alpha = style.WindowFillAlphaDefault; - // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { @@ -3767,7 +3763,7 @@ } // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects. - window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; + window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; // Calculate auto-fit size ImVec2 size_auto_fit; @@ -3981,27 +3977,26 @@ } // Scrollbars - window->ScrollbarY = (flags & ImGuiWindowFlags_ForceVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_ForceHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; // Window background - if (bg_alpha > 0.0f) - { - ImGuiCol col_idx; - if ((flags & ImGuiWindowFlags_ComboBox) != 0) - col_idx = ImGuiCol_ComboBg; - else if ((flags & ImGuiWindowFlags_Tooltip) != 0) - col_idx = ImGuiCol_TooltipBg; - else if ((flags & ImGuiWindowFlags_Popup) != 0) - col_idx = ImGuiCol_WindowBg; - else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) - col_idx = ImGuiCol_ChildWindowBg; - else - col_idx = ImGuiCol_WindowBg; - window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, GetColorU32(col_idx, bg_alpha), window_rounding); - } + // Default alpha + ImGuiCol bg_color_idx = ImGuiCol_WindowBg; + if ((flags & ImGuiWindowFlags_ComboBox) != 0) + bg_color_idx = ImGuiCol_ComboBg; + else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0) + bg_color_idx = ImGuiCol_PopupBg; + else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) + bg_color_idx = ImGuiCol_ChildWindowBg; + ImVec4 bg_color = style.Colors[bg_color_idx]; + if (bg_alpha >= 0.0f) + bg_color.w = bg_alpha; + bg_color.w *= style.Alpha; + if (bg_color.w > 0.0f) + window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding); // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) @@ -4521,6 +4516,7 @@ case ImGuiCol_TextDisabled: return "TextDisabled"; case ImGuiCol_WindowBg: return "WindowBg"; case ImGuiCol_ChildWindowBg: return "ChildWindowBg"; + case ImGuiCol_PopupBg: return "PopupBg"; case ImGuiCol_Border: return "Border"; case ImGuiCol_BorderShadow: return "BorderShadow"; case ImGuiCol_FrameBg: return "FrameBg"; @@ -4558,7 +4554,6 @@ case ImGuiCol_PlotHistogram: return "PlotHistogram"; case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; - case ImGuiCol_TooltipBg: return "TooltipBg"; case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; } IM_ASSERT(0); @@ -7104,9 +7099,9 @@ static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; } -static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } #ifdef __APPLE__ // FIXME: Move setting to IO structure +static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } #else static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } @@ -7310,7 +7305,6 @@ return false; } draw_window = GetCurrentWindow(); - draw_window->DC.CursorPos += style.FramePadding; size.x -= draw_window->ScrollbarSizes.x; } else @@ -8501,7 +8495,7 @@ bool want_open = false, want_close = false; if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { - // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers so menus feel more reactive. + // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; if (g.HoveredWindow == window && g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) { diff --git a/imgui.h b/imgui.h index c7eaa1b..3641824 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.48 WIP" +#define IMGUI_VERSION "1.49 WIP" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API @@ -114,7 +114,7 @@ // Window IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // ". this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. + IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. IMGUI_API void End(); // finish appending to current window, pop it off the window stack. IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " @@ -316,7 +316,7 @@ IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); - IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node to be opened. + IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened. // Widgets: Selectable / Lists IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height @@ -467,11 +467,12 @@ ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar - ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You need to use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. + ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) - ImGuiWindowFlags_ForceVerticalScrollbar = 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) - ImGuiWindowFlags_ForceHorizontalScrollbar=1 << 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) + ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() @@ -546,8 +547,9 @@ { ImGuiCol_Text, ImGuiCol_TextDisabled, - ImGuiCol_WindowBg, - ImGuiCol_ChildWindowBg, + ImGuiCol_WindowBg, // Background of normal windows + ImGuiCol_ChildWindowBg, // Background of child windows + ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows ImGuiCol_Border, ImGuiCol_BorderShadow, ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input @@ -585,7 +587,6 @@ ImGuiCol_PlotHistogram, ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, - ImGuiCol_TooltipBg, ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active ImGuiCol_COUNT }; @@ -667,7 +668,6 @@ ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - float WindowFillAlphaDefault; // Default alpha of window background, if not specified in ImGui::Begin() float IndentSpacing; // Horizontal indentation when e.g. entering a tree node float ColumnsMinSpacing; // Minimum horizontal spacing between two columns float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -895,6 +895,7 @@ int CountGrep; ImGuiTextFilter(const char* default_filter = ""); + ~ImGuiTextFilter() {} void Clear() { InputBuf[0] = 0; Build(); } bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build bool PassFilter(const char* text, const char* text_end = NULL) const; @@ -1157,7 +1158,7 @@ // Stateful path API, add points then finish with PathFill() or PathStroke() inline void PathClear() { _Path.resize(0); } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } - inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || _Path[_Path.Size-1].x != pos.x || _Path[_Path.Size-1].y != pos.y) _Path.push_back(pos); } + inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 132e8e7..fdf2d8e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (demo code) // Don't remove this file from your project! It is useful reference code that you can execute. @@ -139,7 +139,6 @@ static bool no_scrollbar = false; static bool no_collapse = false; static bool no_menu = false; - static float bg_alpha = -0.01f; // <0: default // Demonstrate the various window flags. Typically you would just use the default. ImGuiWindowFlags window_flags = 0; @@ -150,7 +149,8 @@ if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; - if (!ImGui::Begin("ImGui Demo", p_opened, ImVec2(550,680), bg_alpha, window_flags)) + ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver); + if (!ImGui::Begin("ImGui Demo", p_opened, window_flags)) { // Early out if the window is collapsed, as an optimization. ImGui::End(); @@ -211,10 +211,6 @@ ImGui::Checkbox("No collapse", &no_collapse); ImGui::Checkbox("No menu", &no_menu); - ImGui::PushItemWidth(100); - ImGui::DragFloat("Window Fill Alpha", &bg_alpha, 0.005f, -0.01f, 1.0f, bg_alpha < 0.0f ? "(default)" : "%.3f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. - ImGui::PopItemWidth(); - if (ImGui::TreeNode("Style")) { ImGui::ShowStyleEditor(); @@ -1500,7 +1496,7 @@ ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); } ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("KeyMods: %s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); + ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false"); ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false"); @@ -1561,7 +1557,6 @@ ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f); if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f; ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. - ImGui::DragFloat("Window Fill Alpha Default", &style.WindowFillAlphaDefault, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::PopItemWidth(); ImGui::TreePop(); } @@ -1618,7 +1613,7 @@ static ImGuiTextFilter filter; filter.Draw("Filter colors", 200); - ImGui::BeginChild("#colors", ImVec2(0, 300), true); + ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGui::PushItemWidth(-160); for (int i = 0; i < ImGuiCol_COUNT; i++) { @@ -2299,12 +2294,12 @@ { ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. - bool opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid); + bool is_opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid); ImGui::NextColumn(); ImGui::AlignFirstTextHeightToWidgets(); ImGui::Text("my sailor is rich"); ImGui::NextColumn(); - if (opened) + if (is_opened) { static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f }; for (int i = 0; i < 8; i++) diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp new file mode 100644 index 0000000..33d8e99 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -0,0 +1,935 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// GLFW +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include +#ifdef _WIN32 +#undef APIENTRY +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "imgui_impl_glfw_vulkan.h" + +// GLFW Data +static GLFWwindow* g_Window = NULL; +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; + +// Vulkan Data +static VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; + +static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; +static size_t g_BufferMemoryAlignment = 256; +static VkPipelineCreateFlags g_PipelineCreateFlags = 0; +static int g_FrameIndex = 0; + +static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; +static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; +static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; +static VkPipeline g_Pipeline = VK_NULL_HANDLE; + +static VkSampler g_FontSampler = VK_NULL_HANDLE; +static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; +static VkImage g_FontImage = VK_NULL_HANDLE; +static VkImageView g_FontView = VK_NULL_HANDLE; + +static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; + +static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; +static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; + +static unsigned char __glsl_shader_vert_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, + 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x41, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x06, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7f, 0x02, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x7f, 0x02, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x2e, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x60, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x41, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0xaa, 0x26, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xaa, 0x26, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x91, 0x02, 0x00, 0x00, + 0xea, 0x50, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xea, 0x50, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0xa1, 0x41, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x84, 0x36, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xa1, 0x41, 0x00, 0x00, 0x84, 0x36, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0x17, 0x2f, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_vert_spv_len = 1172; + +static unsigned char __glsl_shader_frag_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x7a, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x04, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x03, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x5d, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x0b, 0x40, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x90, 0x02, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x35, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x57, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xb9, 0x46, 0x00, 0x00, + 0xc0, 0x36, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0xe4, 0x23, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x00, + 0xb9, 0x46, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x0c, 0x00, 0x00, + 0xe4, 0x23, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_frag_spv_len = 660; + +static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<TotalVtxCount * sizeof(ImDrawVert); + if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) + { + if (g_VertexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); + if (g_VertexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); + size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; + } + + // Create the Index Buffer: + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) + { + if (g_IndexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); + if (g_IndexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); + size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = index_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_IndexBufferSize[g_FrameIndex] = index_buffer_size; + } + + // Upload Vertex and index Data: + { + ImDrawVert* vtx_dst; + ImDrawIdx* idx_dst; + err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].size = vertex_size; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].size = index_size; + err = vkFlushMappedMemoryRanges(g_Device, 2, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + } + + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = {g_DescriptorSet}; + vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; + VkDeviceSize vertex_offset[1] = {0}; + vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + } + + // Setup scale and translation: + { + float scale[2]; + scale[0] = 2.0f/io.DisplaySize.x; + scale[1] = 2.0f/io.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f; + translate[1] = -1.0f; + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + VkRect2D scissor; + scissor.offset.x = static_cast(pcmd->ClipRect.x); + scissor.offset.y = static_cast(pcmd->ClipRect.y); + scissor.extent.width = static_cast(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = static_cast(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? + vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +static const char* ImGui_ImplGlfwVulkan_GetClipboardText() +{ + return glfwGetClipboardString(g_Window); +} + +static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) +{ + glfwSetClipboardString(g_Window, text); +} + +void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +{ + if (action == GLFW_PRESS && button >= 0 && button < 3) + g_MousePressed[button] = true; +} + +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +{ + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. +} + +void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +} + +void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +{ + ImGuiIO& io = ImGui::GetIO(); + if (c > 0 && c < 0x10000) + io.AddInputCharacter((unsigned short)c); +} + +bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) +{ + ImGuiIO& io = ImGui::GetIO(); + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width*height*4*sizeof(char); + + VkResult err; + + // Create the Image: + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.extent.width = width; + info.extent.height = height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetImageMemoryRequirements(g_Device, g_FontImage, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create the Image View: + { + VkResult err; + VkImageViewCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.image = g_FontImage; + info.viewType = VK_IMAGE_VIEW_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.levelCount = 1; + info.subresourceRange.layerCount = 1; + err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Update the Descriptor Set: + { + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = g_FontSampler; + desc_image[0].imageView = g_FontView; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = g_DescriptorSet; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL); + } + + // Create the Upload Buffer: + { + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Upload to Buffer: + { + char* map = NULL; + err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); + ImGui_ImplGlfwVulkan_VkResult(err); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_UploadBufferMemory; + range[0].size = upload_size; + err = vkFlushMappedMemoryRanges(g_Device, 1, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_UploadBufferMemory); + } + // Copy to Image: + { + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = g_FontImage; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = g_FontImage; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); + } + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontImage; + + return true; +} + +bool ImGui_ImplGlfwVulkan_CreateDeviceObjects() +{ + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = __glsl_shader_vert_spv_len; + vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module); + ImGui_ImplGlfwVulkan_VkResult(err); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = __glsl_shader_frag_spv_len; + frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_PipelineLayout) + { + VkPushConstantRange push_constants[2] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 2; + push_constants[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[1].offset = sizeof(float) * 2; + push_constants[1].size = sizeof(float) * 2; + VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 2; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.dynamicStateCount = 2; + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = g_PipelineCreateFlags; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = g_PipelineLayout; + info.renderPass = g_RenderPass; + err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline); + ImGui_ImplGlfwVulkan_VkResult(err); + + vkDestroyShaderModule(g_Device, vert_module, g_Allocator); + vkDestroyShaderModule(g_Device, frag_module, g_Allocator); + + return true; +} + +void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects() +{ + if (g_UploadBuffer) + { + vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator); + g_UploadBuffer = VK_NULL_HANDLE; + } + if (g_UploadBufferMemory) + { + vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator); + g_UploadBufferMemory = VK_NULL_HANDLE; + } +} + +void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() +{ + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + for (int i=0; iallocator; + g_Gpu = init_data->gpu; + g_Device = init_data->device; + g_RenderPass = init_data->render_pass; + g_PipelineCache = init_data->pipeline_cache; + g_DescriptorPool = init_data->descriptor_pool; + g_CheckVkResult = init_data->check_vk_result; + + g_Window = window; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; +#ifdef _WIN32 + io.ImeWindowHandle = glfwGetWin32Window(g_Window); +#endif + + if (install_callbacks) + { + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); + } + + ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplGlfwVulkan_Shutdown() +{ + ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplGlfwVulkan_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + glfwGetWindowSize(g_Window, &w, &h); + glfwGetFramebufferSize(g_Window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + double current_time = glfwGetTime(); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } + else + { + io.MousePos = ImVec2(-1,-1); + } + + for (int i = 0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MousePressed[i] = false; + } + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + + // Start the frame + ImGui::NewFrame(); +} +void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) +{ + g_CommandBuffer = command_buffer; + ImGui::Render(); + g_CommandBuffer = VK_NULL_HANDLE; + g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h new file mode 100644 index 0000000..74d35a2 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -0,0 +1,40 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct GLFWwindow; + +#define IMGUI_VK_QUEUED_FRAMES 2 + +struct ImGui_ImplGlfwVulkan_Init_Data +{ + VkAllocationCallbacks* allocator; + VkPhysicalDevice gpu; + VkDevice device; + VkRenderPass render_pass; + VkPipelineCache pipeline_cache; + VkDescriptorPool descriptor_pool; + void (*check_vk_result)(VkResult err); +}; + +IMGUI_API bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data); +IMGUI_API void ImGui_ImplGlfwVulkan_Shutdown(); +IMGUI_API void ImGui_ImplGlfwVulkan_NewFrame(); +IMGUI_API void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + +// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) +// Provided here if you want to chain callbacks. +// You can also handle inputs yourself and use those as a reference. +IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c); + diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp new file mode 100644 index 0000000..130fd87 --- /dev/null +++ b/examples/vulkan_example/main.cpp @@ -0,0 +1,539 @@ +// ImGui - standalone example application for Glfw + Vulkan, using programmable pipeline +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. + +#include + +#include // printf, fprintf +#include // abort +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include + +#include "imgui_impl_glfw_vulkan.h" + +#define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 + +static VkAllocationCallbacks* g_Allocator = NULL; +static VkInstance g_Instance = VK_NULL_HANDLE; +static VkSurfaceKHR g_Surface = VK_NULL_HANDLE; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static uint32_t g_QueueFamily = 0; +static VkQueue g_Queue = VK_NULL_HANDLE; + +static VkFormat g_Format = VK_FORMAT_B8G8R8A8_UNORM; +static VkColorSpaceKHR g_ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; +static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; + +static int fb_width, fb_height; +static uint32_t g_BackBufferIndex = 0; +static uint32_t g_BackBufferCount = 0; +static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; + +static uint32_t g_FrameIndex = 0; +static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; +static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; +static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; +static VkSemaphore g_Semaphore[IMGUI_VK_QUEUED_FRAMES]; + +static VkClearValue g_ClearValue = {}; + +static void check_vk_result(VkResult err) +{ + if (err == 0) return; + printf("VkResult %d\n", err); + if (err < 0) + abort(); +} + +static void resize_vulkan(GLFWwindow* /*window*/, int w, int h) +{ + VkResult err; + VkSwapchainKHR old_swapchain = g_Swapchain; + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + + // Destroy old Framebuffer: + for (uint32_t i=0; iAddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + + // Upload Fonts + { + VkResult err; + err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + check_vk_result(err); + VkCommandBufferBeginInfo begin_info = {}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info); + check_vk_result(err); + + ImGui_ImplGlfwVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); + + VkSubmitInfo end_info = {}; + end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + end_info.commandBufferCount = 1; + end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; + err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + check_vk_result(err); + err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); + check_vk_result(err); + + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + } + + bool show_test_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImColor(114, 144, 154); + + // Main loop + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + ImGui_ImplGlfwVulkan_NewFrame(); + + // 1. Show a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + { + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::ColorEdit3("clear color", (float*)&clear_color); + if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) + { + ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); + ImGui::ShowTestWindow(&show_test_window); + } + + g_ClearValue.color.float32[0] = clear_color.x; + g_ClearValue.color.float32[1] = clear_color.y; + g_ClearValue.color.float32[2] = clear_color.z; + g_ClearValue.color.float32[3] = clear_color.w; + + frame_begin(); + ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); + frame_end(); + } + + // Cleanup + VkResult err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_Shutdown(); + cleanup_vulkan(); + glfwTerminate(); + + return 0; +} diff --git a/imgui.cpp b/imgui.cpp index 8f2b87f..316dea5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (main code and documentation) // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. @@ -152,6 +152,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). + - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - 2016/02/21 (1.48) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to ColorEdit*() functions @@ -506,6 +508,7 @@ - color: add a better color picker (#346) - node/graph editor (#306) - pie menus patterns (#434) + - drag'n drop, dragging helpers (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479) - plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals) - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots) - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value) @@ -694,13 +697,12 @@ WindowMinSize = ImVec2(32,32); // Minimum window size WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text - ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows + ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin() IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -715,8 +717,9 @@ Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input @@ -754,7 +757,6 @@ Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } @@ -1652,7 +1654,7 @@ { ImGuiState& g = *GImGui; IM_ASSERT(g.CurrentWindowStack.Size >= 2); - return g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; + return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) @@ -2339,9 +2341,9 @@ // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices) // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly. - IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. - IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= ((unsigned long long int)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. - + IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. + IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. + out_render_list.push_back(draw_list); GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; @@ -3139,9 +3141,8 @@ void ImGui::BeginTooltip() { - ImGuiState& g = *GImGui; ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; - ImGui::Begin("##Tooltip", NULL, ImVec2(0,0), g.Style.Colors[ImGuiCol_TooltipBg].w, flags); + ImGui::Begin("##Tooltip", NULL, flags); } void ImGui::EndTooltip() @@ -3279,9 +3280,8 @@ ImFormatString(name, 20, "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth else ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame - float alpha = 1.0f; - bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), alpha, flags); + bool opened = ImGui::Begin(name, NULL, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display) @@ -3312,7 +3312,7 @@ } ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; - bool opened = ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), -1.0f, flags); + bool opened = ImGui::Begin(name, p_opened, flags); if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) { ImGui::EndPopup(); @@ -3392,8 +3392,7 @@ char title[256]; ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id); - const float alpha = 1.0f; - bool ret = ImGui::Begin(title, NULL, size, alpha, flags); + bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; @@ -3443,13 +3442,14 @@ const ImGuiStyle& style = g.Style; ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); - return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove | extra_flags); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); } void ImGui::EndChildFrame() { ImGui::EndChild(); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); ImGui::PopStyleColor(); } @@ -3692,10 +3692,6 @@ window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. - // Default alpha - if (bg_alpha < 0.0f) - bg_alpha = style.WindowFillAlphaDefault; - // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { @@ -3767,7 +3763,7 @@ } // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects. - window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; + window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; // Calculate auto-fit size ImVec2 size_auto_fit; @@ -3981,27 +3977,26 @@ } // Scrollbars - window->ScrollbarY = (flags & ImGuiWindowFlags_ForceVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_ForceHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; // Window background - if (bg_alpha > 0.0f) - { - ImGuiCol col_idx; - if ((flags & ImGuiWindowFlags_ComboBox) != 0) - col_idx = ImGuiCol_ComboBg; - else if ((flags & ImGuiWindowFlags_Tooltip) != 0) - col_idx = ImGuiCol_TooltipBg; - else if ((flags & ImGuiWindowFlags_Popup) != 0) - col_idx = ImGuiCol_WindowBg; - else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) - col_idx = ImGuiCol_ChildWindowBg; - else - col_idx = ImGuiCol_WindowBg; - window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, GetColorU32(col_idx, bg_alpha), window_rounding); - } + // Default alpha + ImGuiCol bg_color_idx = ImGuiCol_WindowBg; + if ((flags & ImGuiWindowFlags_ComboBox) != 0) + bg_color_idx = ImGuiCol_ComboBg; + else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0) + bg_color_idx = ImGuiCol_PopupBg; + else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) + bg_color_idx = ImGuiCol_ChildWindowBg; + ImVec4 bg_color = style.Colors[bg_color_idx]; + if (bg_alpha >= 0.0f) + bg_color.w = bg_alpha; + bg_color.w *= style.Alpha; + if (bg_color.w > 0.0f) + window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding); // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) @@ -4521,6 +4516,7 @@ case ImGuiCol_TextDisabled: return "TextDisabled"; case ImGuiCol_WindowBg: return "WindowBg"; case ImGuiCol_ChildWindowBg: return "ChildWindowBg"; + case ImGuiCol_PopupBg: return "PopupBg"; case ImGuiCol_Border: return "Border"; case ImGuiCol_BorderShadow: return "BorderShadow"; case ImGuiCol_FrameBg: return "FrameBg"; @@ -4558,7 +4554,6 @@ case ImGuiCol_PlotHistogram: return "PlotHistogram"; case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; - case ImGuiCol_TooltipBg: return "TooltipBg"; case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; } IM_ASSERT(0); @@ -7104,9 +7099,9 @@ static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; } -static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } #ifdef __APPLE__ // FIXME: Move setting to IO structure +static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } #else static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } @@ -7310,7 +7305,6 @@ return false; } draw_window = GetCurrentWindow(); - draw_window->DC.CursorPos += style.FramePadding; size.x -= draw_window->ScrollbarSizes.x; } else @@ -8501,7 +8495,7 @@ bool want_open = false, want_close = false; if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { - // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers so menus feel more reactive. + // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; if (g.HoveredWindow == window && g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) { diff --git a/imgui.h b/imgui.h index c7eaa1b..3641824 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.48 WIP" +#define IMGUI_VERSION "1.49 WIP" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API @@ -114,7 +114,7 @@ // Window IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // ". this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. + IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. IMGUI_API void End(); // finish appending to current window, pop it off the window stack. IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " @@ -316,7 +316,7 @@ IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); - IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node to be opened. + IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened. // Widgets: Selectable / Lists IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height @@ -467,11 +467,12 @@ ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar - ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You need to use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. + ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) - ImGuiWindowFlags_ForceVerticalScrollbar = 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) - ImGuiWindowFlags_ForceHorizontalScrollbar=1 << 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) + ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() @@ -546,8 +547,9 @@ { ImGuiCol_Text, ImGuiCol_TextDisabled, - ImGuiCol_WindowBg, - ImGuiCol_ChildWindowBg, + ImGuiCol_WindowBg, // Background of normal windows + ImGuiCol_ChildWindowBg, // Background of child windows + ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows ImGuiCol_Border, ImGuiCol_BorderShadow, ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input @@ -585,7 +587,6 @@ ImGuiCol_PlotHistogram, ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, - ImGuiCol_TooltipBg, ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active ImGuiCol_COUNT }; @@ -667,7 +668,6 @@ ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - float WindowFillAlphaDefault; // Default alpha of window background, if not specified in ImGui::Begin() float IndentSpacing; // Horizontal indentation when e.g. entering a tree node float ColumnsMinSpacing; // Minimum horizontal spacing between two columns float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -895,6 +895,7 @@ int CountGrep; ImGuiTextFilter(const char* default_filter = ""); + ~ImGuiTextFilter() {} void Clear() { InputBuf[0] = 0; Build(); } bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build bool PassFilter(const char* text, const char* text_end = NULL) const; @@ -1157,7 +1158,7 @@ // Stateful path API, add points then finish with PathFill() or PathStroke() inline void PathClear() { _Path.resize(0); } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } - inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || _Path[_Path.Size-1].x != pos.x || _Path[_Path.Size-1].y != pos.y) _Path.push_back(pos); } + inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 132e8e7..fdf2d8e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (demo code) // Don't remove this file from your project! It is useful reference code that you can execute. @@ -139,7 +139,6 @@ static bool no_scrollbar = false; static bool no_collapse = false; static bool no_menu = false; - static float bg_alpha = -0.01f; // <0: default // Demonstrate the various window flags. Typically you would just use the default. ImGuiWindowFlags window_flags = 0; @@ -150,7 +149,8 @@ if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; - if (!ImGui::Begin("ImGui Demo", p_opened, ImVec2(550,680), bg_alpha, window_flags)) + ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver); + if (!ImGui::Begin("ImGui Demo", p_opened, window_flags)) { // Early out if the window is collapsed, as an optimization. ImGui::End(); @@ -211,10 +211,6 @@ ImGui::Checkbox("No collapse", &no_collapse); ImGui::Checkbox("No menu", &no_menu); - ImGui::PushItemWidth(100); - ImGui::DragFloat("Window Fill Alpha", &bg_alpha, 0.005f, -0.01f, 1.0f, bg_alpha < 0.0f ? "(default)" : "%.3f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. - ImGui::PopItemWidth(); - if (ImGui::TreeNode("Style")) { ImGui::ShowStyleEditor(); @@ -1500,7 +1496,7 @@ ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); } ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("KeyMods: %s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); + ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false"); ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false"); @@ -1561,7 +1557,6 @@ ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f); if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f; ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. - ImGui::DragFloat("Window Fill Alpha Default", &style.WindowFillAlphaDefault, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::PopItemWidth(); ImGui::TreePop(); } @@ -1618,7 +1613,7 @@ static ImGuiTextFilter filter; filter.Draw("Filter colors", 200); - ImGui::BeginChild("#colors", ImVec2(0, 300), true); + ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGui::PushItemWidth(-160); for (int i = 0; i < ImGuiCol_COUNT; i++) { @@ -2299,12 +2294,12 @@ { ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. - bool opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid); + bool is_opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid); ImGui::NextColumn(); ImGui::AlignFirstTextHeightToWidgets(); ImGui::Text("my sailor is rich"); ImGui::NextColumn(); - if (opened) + if (is_opened) { static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f }; for (int i = 0; i < 8; i++) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 95871b6..1d26856 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (drawing and font code) // Contains implementation for diff --git a/examples/README.txt b/examples/README.txt index f8e0c55..df6fe87 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -63,9 +63,9 @@ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. -ios_example/ - iOS example. - Using Synergy to access keyboard/mouse data from server computer. +apple_example/ + OSX & iOS example. + On iOS, Using Synergy to access keyboard/mouse data from server computer. Synergy keyboard integration is rather hacky. sdl_opengl_example/ @@ -79,4 +79,8 @@ marmalade_example/ Marmalade example using IwGx - + +vulkan_example/ + Vulkan example. + This is quite long and tedious, because: Vulkan. + diff --git a/examples/apple_example/.gitignore b/examples/apple_example/.gitignore new file mode 100644 index 0000000..8feda89 --- /dev/null +++ b/examples/apple_example/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +imguiex.xcodeproj/project.xcworkspace/ +imguiex.xcodeproj/xcuserdata/ \ No newline at end of file diff --git a/examples/apple_example/README.md b/examples/apple_example/README.md new file mode 100644 index 0000000..339f6bf --- /dev/null +++ b/examples/apple_example/README.md @@ -0,0 +1,41 @@ +# iOS / OSX example + +## Introduction + +This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/) to share mouse/keyboard on an iOS device. + +It is a rather complex and messy example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. **The opengl3_example/ should also work on OS X and is much simpler.** This is an integration for iOS with Synergy. + +Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. + +## How to Use on iOS + +* In Synergy, go to Preferences, and uncheck "Use SSL encryption" +* Run the example app. +* Tap the "servername" button in the corner +* Enter the name or the IP of your synergy host +* If you had previously connected to a server, you may need to kill and re-start the app. + +## How to Build on OSX + +* Make sure you have install `brew`, if not, please refer to [Homebrew Website](http://brew.sh) +* Run the command: `brew install glfw3` +* Double click `imguiex.xcodeproj` and select `imguiex-osx` scheme +* Click `Run` button + +## Notes and TODOs + +Things that would be nice but I didn't get around to doing: + +* iOS software keyboard not supported for text inputs +* iOS hardware (bluetooth) keyboards not supported +* Graceful disconnect/reconnect from uSynergy. +* Copy/Paste not well-supported + +## C++ on iOS / OSX + +ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. + +Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. + +In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/apple_example/imguiex-ios/AppDelegate.h b/examples/apple_example/imguiex-ios/AppDelegate.h new file mode 100644 index 0000000..82f1542 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.h @@ -0,0 +1,13 @@ +// +// AppDelegate.h +// imguiex + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/examples/apple_example/imguiex-ios/AppDelegate.m b/examples/apple_example/imguiex-ios/AppDelegate.m new file mode 100644 index 0000000..ab83101 --- /dev/null +++ b/examples/apple_example/imguiex-ios/AppDelegate.m @@ -0,0 +1,41 @@ +// +// AppDelegate.m +// imguiex + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..5717c00 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/LaunchScreen.xib @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard new file mode 100644 index 0000000..90dfb2e --- /dev/null +++ b/examples/apple_example/imguiex-ios/Base.lproj/Main.storyboard @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/apple_example/imguiex-ios/GameViewController.h b/examples/apple_example/imguiex-ios/GameViewController.h new file mode 100644 index 0000000..3323cfd --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.h @@ -0,0 +1,12 @@ +// +// GameViewController.h +// imguiex + +// This is the OpenGL Example template from XCode, modified to support ImGui + +#import +#import + +@interface GameViewController : GLKViewController + +@end diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m new file mode 100644 index 0000000..e902f7a --- /dev/null +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -0,0 +1,481 @@ +// +// GameViewController.m +// imguiex +// +#import "GameViewController.h" +#import + +#import "imgui_impl_ios.h" +#import "debug_hud.h" + +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +#define SERVERNAME_KEY @"ServerName" + +#define SERVERNAME_ALERT_TAG (10) + +// Uniform index. +enum +{ + UNIFORM_MODELVIEWPROJECTION_MATRIX, + UNIFORM_NORMAL_MATRIX, + UNIFORM_DIFFUSE_COLOR, + + NUM_UNIFORMS +}; +GLint uniforms[NUM_UNIFORMS]; + +// Attribute index. +enum +{ + ATTRIB_VERTEX, + ATTRIB_NORMAL, + NUM_ATTRIBUTES +}; + +GLfloat gCubeVertexData[216] = +{ + // Data layout for each line below is: + // positionX, positionY, positionZ, normalX, normalY, normalZ, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f +}; + +@interface GameViewController () +{ + GLuint _program; + + GLKMatrix4 _modelViewProjectionMatrix; + GLKMatrix3 _normalMatrix; + float _rotation; + + GLuint _vertexArray; + GLuint _vertexBuffer; + + DebugHUD _hud; +} +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKBaseEffect *effect; +@property (strong, nonatomic) ImGuiHelper *imgui; +@property (weak, nonatomic) IBOutlet UIButton *btnServername; + +@property (strong, nonatomic) NSString *serverName; + +- (IBAction)onServernameTapped:(id)sender; + +- (void)setupGL; +- (void)tearDownGL; + +- (BOOL)loadShaders; +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; +- (BOOL)linkProgram:(GLuint)prog; +- (BOOL)validateProgram:(GLuint)prog; +@end + +@implementation GameViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + + if (!self.context) { + NSLog(@"Failed to create ES context"); + } + + GLKView *view = (GLKView *)self.view; + view.context = self.context; + view.drawableDepthFormat = GLKViewDrawableDepthFormat24; + + [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + + [self setupGL]; + + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; + self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; + if (self.serverName) + { + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + [self.imgui connectServer: self.serverName ]; + } + + DebugHUD_InitDefaults( &_hud ); +} + +- (void)dealloc +{ + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + + if ([self isViewLoaded] && ([[self view] window] == nil)) { + self.view = nil; + + [self tearDownGL]; + + if ([EAGLContext currentContext] == self.context) { + [EAGLContext setCurrentContext:nil]; + } + self.context = nil; + } + + // Dispose of any resources that can be recreated. +} + + +- (BOOL)prefersStatusBarHidden { + return YES; +} + +- (IBAction)onServernameTapped:(id)sender +{ + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to + [alert show]; +} + +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex +{ + if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) + { + // This is really janky. I usually just hardcode the servername since I'm building it anyway. + // If you want to properly handle updating the server, you'll want to tear down and recreate + // the usynergy stuff in connectServer + BOOL serverNameWasSet = self.serverName.length > 0; + NSString *serverName = [[alertView textFieldAtIndex:0] text]; + + if ([serverName length] > 0) { + self.serverName = serverName; + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; + [userDefaults synchronize]; + + [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; + + // If we hadn't previously connected, try now + if (!serverNameWasSet) { + [self.imgui connectServer:self.serverName]; + } + else + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" + message:@"Restart the app to connect the server" + delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; + [alert show]; + } + } + } +} + +- (void)setupGL +{ + [EAGLContext setCurrentContext:self.context]; + + [self loadShaders]; + + self.effect = [[GLKBaseEffect alloc] init]; + self.effect.light0.enabled = GL_TRUE; + self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); + + glEnable(GL_DEPTH_TEST); + + glGenVertexArraysOES(1, &_vertexArray); + glBindVertexArrayOES(_vertexArray); + + glGenBuffers(1, &_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); + + glEnableVertexAttribArray(GLKVertexAttribPosition); + glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(GLKVertexAttribNormal); + glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); + + glBindVertexArrayOES(0); + + +} + +- (void)tearDownGL +{ + [EAGLContext setCurrentContext:self.context]; + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteVertexArraysOES(1, &_vertexArray); + + self.effect = nil; + + if (_program) { + glDeleteProgram(_program); + _program = 0; + } +} + +#pragma mark - GLKView and GLKViewController delegate methods + +- (void)update +{ + float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); + GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); + + self.effect.transform.projectionMatrix = projectionMatrix; + + GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); + baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); + + // Compute the model view matrix for the object rendered with GLKit + GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + self.effect.transform.modelviewMatrix = modelViewMatrix; + + // Compute the model view matrix for the object rendered with ES2 + modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); + modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); + modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); + + _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); + + _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); + + _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); +} + + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect +{ + glClearColor(0.65f, 0.65f, 0.65f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glBindVertexArrayOES(_vertexArray); + + // Render the object with GLKit + [self.effect prepareToDraw]; + + glDrawArrays(GL_TRIANGLES, 0, 36); + + // Render the object again with ES2 + glUseProgram(_program); + + glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); + glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); + glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); + + glDrawArrays(GL_TRIANGLES, 0, 36); + + [self.imgui newFrame]; + + // Now do our ImGUI UI + DebugHUD_DoInterface( &_hud ); + + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); + + // Now render Imgui + [self.imgui render]; + +} + +#pragma mark - OpenGL ES 2 shader compilation + +- (BOOL)loadShaders +{ + GLuint vertShader, fragShader; + NSString *vertShaderPathname, *fragShaderPathname; + + // Create shader program. + _program = glCreateProgram(); + + // Create and compile vertex shader. + vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; + if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { + NSLog(@"Failed to compile vertex shader"); + return NO; + } + + // Create and compile fragment shader. + fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; + if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { + NSLog(@"Failed to compile fragment shader"); + return NO; + } + + // Attach vertex shader to program. + glAttachShader(_program, vertShader); + + // Attach fragment shader to program. + glAttachShader(_program, fragShader); + + // Bind attribute locations. + // This needs to be done prior to linking. + glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); + glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); + + // Link program. + if (![self linkProgram:_program]) { + NSLog(@"Failed to link program: %d", _program); + + if (vertShader) { + glDeleteShader(vertShader); + vertShader = 0; + } + if (fragShader) { + glDeleteShader(fragShader); + fragShader = 0; + } + if (_program) { + glDeleteProgram(_program); + _program = 0; + } + + return NO; + } + + // Get uniform locations. + uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); + uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); + uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); + + // Release vertex and fragment shaders. + if (vertShader) { + glDetachShader(_program, vertShader); + glDeleteShader(vertShader); + } + if (fragShader) { + glDetachShader(_program, fragShader); + glDeleteShader(fragShader); + } + + return YES; +} + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file +{ + GLint status; + const GLchar *source; + + source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; + if (!source) { + NSLog(@"Failed to load vertex shader"); + return NO; + } + + *shader = glCreateShader(type); + glShaderSource(*shader, 1, &source, NULL); + glCompileShader(*shader); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(*shader, logLength, &logLength, log); + NSLog(@"Shader compile log:\n%s", log); + free(log); + } +#endif + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + if (status == 0) { + glDeleteShader(*shader); + return NO; + } + + return YES; +} + +- (BOOL)linkProgram:(GLuint)prog +{ + GLint status; + glLinkProgram(prog); + +#if defined(DEBUG) + GLint logLength; + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program link log:\n%s", log); + free(log); + } +#endif + + glGetProgramiv(prog, GL_LINK_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +- (BOOL)validateProgram:(GLuint)prog +{ + GLint logLength, status; + + glValidateProgram(prog); + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetProgramInfoLog(prog, logLength, &logLength, log); + NSLog(@"Program validate log:\n%s", log); + free(log); + } + + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (status == 0) { + return NO; + } + + return YES; +} + +@end diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..06b60d8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,77 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@2x~iphone.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon_imgui_60@3x~iphone.png", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon_imgui_76@2x~ipad.png", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png new file mode 100644 index 0000000..d728bc3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png new file mode 100644 index 0000000..67b08b8 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png new file mode 100644 index 0000000..ae88e04 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/Info.plist b/examples/apple_example/imguiex-ios/Info.plist new file mode 100644 index 0000000..bc6f548 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.fsh b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh new file mode 100644 index 0000000..4000524 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.fsh @@ -0,0 +1,10 @@ +// +// Shader.fsh +// imguiex + +varying lowp vec4 colorVarying; + +void main() +{ + gl_FragColor = colorVarying; +} diff --git a/examples/apple_example/imguiex-ios/Shaders/Shader.vsh b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh new file mode 100644 index 0000000..313c3d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/Shaders/Shader.vsh @@ -0,0 +1,25 @@ +// +// Shader.vsh +// imguiex + +attribute vec4 position; +attribute vec3 normal; + +varying lowp vec4 colorVarying; + +uniform vec3 diffuseColor; +uniform mat4 modelViewProjectionMatrix; +uniform mat3 normalMatrix; + +void main() +{ + vec3 eyeNormal = normalize(normalMatrix * normal); + vec3 lightPosition = vec3(0.0, 0.0, 1.0); + + float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); + + vec3 colorLit = diffuseColor * nDotVP; + colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); + + gl_Position = modelViewProjectionMatrix * position; +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp new file mode 100644 index 0000000..c75938a --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -0,0 +1,45 @@ +// +// debug_hud.cpp +// imguiex + +#include + +#include "debug_hud.h" +#include "imgui.h" + +void DebugHUD_InitDefaults( DebugHUD *hud ) +{ + hud->show_test_window = true; + hud->show_example_window = true; + hud->rotation_speed = 15.0f; + + hud->cubeColor1[0] = 0.4f; + hud->cubeColor1[1] = 0.4f; + hud->cubeColor1[2] = 1.0f; + hud->cubeColor1[3] = 1.0f; + + hud->cubeColor2[0] = 1.0f; + hud->cubeColor2[1] = 0.4f; + hud->cubeColor2[2] = 0.4f; + hud->cubeColor2[3] = 1.0f; +} + +void DebugHUD_DoInterface( DebugHUD *hud ) +{ + if (hud->show_test_window) + { + ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::ShowTestWindow( &hud->show_test_window ); + } + + if (hud->show_example_window) + { + ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); + ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); + ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); + ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); + ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + ImGui::End(); + } +} diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h new file mode 100644 index 0000000..17122f5 --- /dev/null +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -0,0 +1,25 @@ +// +// debug_hud.h +// imguiex + +#pragma once + +typedef struct DebugHUD +{ + bool show_test_window; + bool show_example_window; + float rotation_speed; + float cubeColor1[4]; + float cubeColor2[4]; +} DebugHUD; + +#if __cplusplus +extern "C" { +#endif + +void DebugHUD_InitDefaults( DebugHUD *hud ); +void DebugHUD_DoInterface( DebugHUD *hud ); + +#if __cplusplus +} +#endif diff --git a/examples/apple_example/imguiex-ios/imgui_ex_icon.png b/examples/apple_example/imguiex-ios/imgui_ex_icon.png new file mode 100644 index 0000000..820e4d7 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_ex_icon.png Binary files differ diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.h b/examples/apple_example/imguiex-ios/imgui_impl_ios.h new file mode 100644 index 0000000..9b01dd3 --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.h @@ -0,0 +1,22 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +// by Joel Davis (joeld42@gmail.com) + +#pragma once + +#include +#include + +@interface ImGuiHelper : NSObject + +- (id) initWithView: (UIView *)view; + +- (void)connectServer: (NSString*)serverName; + +- (void)render; +- (void)newFrame; + +@end diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm new file mode 100644 index 0000000..b286c4d --- /dev/null +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -0,0 +1,803 @@ +// ImGui iOS+OpenGL+Synergy binding +// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. +// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. + +#import +#import + +#include +#include +#include +#include + +#include "imgui_impl_ios.h" +#include "imgui.h" + +#include "uSynergy.h" + +// From Carbon HIToolbox/Events.h +// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 +enum { + kVK_ANSI_A = 0x00, + kVK_ANSI_S = 0x01, + kVK_ANSI_D = 0x02, + kVK_ANSI_F = 0x03, + kVK_ANSI_H = 0x04, + kVK_ANSI_G = 0x05, + kVK_ANSI_Z = 0x06, + kVK_ANSI_X = 0x07, + kVK_ANSI_C = 0x08, + kVK_ANSI_V = 0x09, + kVK_ANSI_B = 0x0B, + kVK_ANSI_Q = 0x0C, + kVK_ANSI_W = 0x0D, + kVK_ANSI_E = 0x0E, + kVK_ANSI_R = 0x0F, + kVK_ANSI_Y = 0x10, + kVK_ANSI_T = 0x11, + kVK_ANSI_1 = 0x12, + kVK_ANSI_2 = 0x13, + kVK_ANSI_3 = 0x14, + kVK_ANSI_4 = 0x15, + kVK_ANSI_6 = 0x16, + kVK_ANSI_5 = 0x17, + kVK_ANSI_Equal = 0x18, + kVK_ANSI_9 = 0x19, + kVK_ANSI_7 = 0x1A, + kVK_ANSI_Minus = 0x1B, + kVK_ANSI_8 = 0x1C, + kVK_ANSI_0 = 0x1D, + kVK_ANSI_RightBracket = 0x1E, + kVK_ANSI_O = 0x1F, + kVK_ANSI_U = 0x20, + kVK_ANSI_LeftBracket = 0x21, + kVK_ANSI_I = 0x22, + kVK_ANSI_P = 0x23, + kVK_ANSI_L = 0x25, + kVK_ANSI_J = 0x26, + kVK_ANSI_Quote = 0x27, + kVK_ANSI_K = 0x28, + kVK_ANSI_Semicolon = 0x29, + kVK_ANSI_Backslash = 0x2A, + kVK_ANSI_Comma = 0x2B, + kVK_ANSI_Slash = 0x2C, + kVK_ANSI_N = 0x2D, + kVK_ANSI_M = 0x2E, + kVK_ANSI_Period = 0x2F, + kVK_ANSI_Grave = 0x32, + kVK_ANSI_KeypadDecimal = 0x41, + kVK_ANSI_KeypadMultiply = 0x43, + kVK_ANSI_KeypadPlus = 0x45, + kVK_ANSI_KeypadClear = 0x47, + kVK_ANSI_KeypadDivide = 0x4B, + kVK_ANSI_KeypadEnter = 0x4C, + kVK_ANSI_KeypadMinus = 0x4E, + kVK_ANSI_KeypadEquals = 0x51, + kVK_ANSI_Keypad0 = 0x52, + kVK_ANSI_Keypad1 = 0x53, + kVK_ANSI_Keypad2 = 0x54, + kVK_ANSI_Keypad3 = 0x55, + kVK_ANSI_Keypad4 = 0x56, + kVK_ANSI_Keypad5 = 0x57, + kVK_ANSI_Keypad6 = 0x58, + kVK_ANSI_Keypad7 = 0x59, + kVK_ANSI_Keypad8 = 0x5B, + kVK_ANSI_Keypad9 = 0x5C +}; + +/* keycodes for keys that are independent of keyboard layout*/ +enum { + kVK_Return = 0x24, + kVK_Tab = 0x30, + kVK_Space = 0x31, + kVK_Delete = 0x33, + kVK_Escape = 0x35, + kVK_Command = 0x37, + kVK_Shift = 0x38, + kVK_CapsLock = 0x39, + kVK_Option = 0x3A, + kVK_Control = 0x3B, + kVK_RightShift = 0x3C, + kVK_RightOption = 0x3D, + kVK_RightControl = 0x3E, + kVK_Function = 0x3F, + kVK_F17 = 0x40, + kVK_VolumeUp = 0x48, + kVK_VolumeDown = 0x49, + kVK_Mute = 0x4A, + kVK_F18 = 0x4F, + kVK_F19 = 0x50, + kVK_F20 = 0x5A, + kVK_F5 = 0x60, + kVK_F6 = 0x61, + kVK_F7 = 0x62, + kVK_F3 = 0x63, + kVK_F8 = 0x64, + kVK_F9 = 0x65, + kVK_F11 = 0x67, + kVK_F13 = 0x69, + kVK_F16 = 0x6A, + kVK_F14 = 0x6B, + kVK_F10 = 0x6D, + kVK_F12 = 0x6F, + kVK_F15 = 0x71, + kVK_Help = 0x72, + kVK_Home = 0x73, + kVK_PageUp = 0x74, + kVK_ForwardDelete = 0x75, + kVK_F4 = 0x76, + kVK_End = 0x77, + kVK_F2 = 0x78, + kVK_PageDown = 0x79, + kVK_F1 = 0x7A, + kVK_LeftArrow = 0x7B, + kVK_RightArrow = 0x7C, + kVK_DownArrow = 0x7D, + kVK_UpArrow = 0x7E +}; + +static char g_keycodeCharUnshifted[256] = {}; +static char g_keycodeCharShifted[256] = {}; + +//static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_mouseWheelX = 0.0f; +static float g_mouseWheelY = 0.0f; + +static GLuint g_FontTexture = 0; +static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; +static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; +static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; +static size_t g_VboSize = 0; +static unsigned int g_VboHandle = 0, g_VaoHandle = 0; +static float g_displayScale; + +static int usynergy_sockfd; +static bool g_synergyPtrActive = false; +static uint16_t g_mousePosX = 0; +static uint16_t g_mousePosY = 0; + +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); +bool ImGui_ImplIOS_CreateDeviceObjects(); + +static NSString *g_serverName; + +uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) +{ + // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since + // uSynergy does not support SSL. + + NSLog( @"Connect Func!"); + struct addrinfo hints, *res; + + // first, load up address structs with getaddrinfo(): + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever + hints.ai_socktype = SOCK_STREAM; + + // get server address + getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); + + if (!res) + { + NSLog( @"Could not find server: %@", g_serverName ); + return USYNERGY_FALSE; + } + + // make a socket: + usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + + // connect it to the address and port we passed in to getaddrinfo(): + int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); + if (!ret) { + NSLog( @"Connect suceeded..."); + } else { + NSLog( @"Connect failed, %d", ret ); + } + + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) +{ +// NSLog( @"Send Func" ); + send( usynergy_sockfd, buffer, length, 0 ); + + return USYNERGY_TRUE; +} + +uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) +{ + *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); + + return USYNERGY_TRUE; +} + +void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) +{ + usleep( timeMs * 1000 ); +} + +uint32_t ImGui_GetTimeFunc() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); +} + +void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) +{ + puts(text); +} + +void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) +{ + g_synergyPtrActive = active; +// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); +} + +void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, + uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) +{ +// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); + uSynergyContext *ctx = (uSynergyContext*)cookie; + g_mousePosX = x; + g_mousePosY = y; + g_mouseWheelX = wheelX; + g_mouseWheelY = wheelY; + g_MousePressed[0] = buttonLeft; + g_MousePressed[1] = buttonMiddle; + g_MousePressed[2] = buttonRight; + + ctx->m_mouseWheelX = 0; + ctx->m_mouseWheelY = 0; +} + +void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, + uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) +{ + int scanCode = key-1; +// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[key] = down; + io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); + io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); + io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); + io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); + + // Add this as keyboard input + if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) + { + // If this key maps to a character input, apply it + int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; + io.AddInputCharacter((unsigned short)charForKeycode); + } + +} + +void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) +{ + printf("Synergy: joystick callback TODO\n"); +} + +void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) +{ + printf("Synergy: clipboard callback TODO\n" ); +} + + +@interface ImGuiHelper () +{ + BOOL _mouseDown; + BOOL _mouseTapped; + CGPoint _touchPos; + + uSynergyContext _synergyCtx; + dispatch_queue_t _synergyQueue; +} +@property (nonatomic, weak) UIView *view; +@property (nonatomic, strong) NSString *serverName; + +@end + +@implementation ImGuiHelper + +- (id) initWithView: (UIView *)view +{ + self = [super init]; + if (self) + { + self.view = view; + + [self setupImGuiHooks]; + } + return self; +} + +- (void)setupKeymaps +{ + // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, + // but this was the best I could come up with. There are some device independent API's available + // to convert scan codes to unicode characters, but these are only available on mac and not + // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do + // this or any way to get the character codes out of usynergy. + g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; + g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; + g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; + g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; + g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; + g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; + g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; + g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; + g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; + g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; + g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; + g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; + g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; + g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; + g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; + g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; + g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; + g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; + g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; + g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; + g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; + g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; + g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; + g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; + g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; + g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; + g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; + g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; + g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; + g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; + g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; + g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; + g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; + g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharUnshifted[ kVK_Space ]=' '; + + g_keycodeCharShifted[ kVK_ANSI_A ]='A'; + g_keycodeCharShifted[ kVK_ANSI_S ]='S'; + g_keycodeCharShifted[ kVK_ANSI_D ]='D'; + g_keycodeCharShifted[ kVK_ANSI_F ]='F'; + g_keycodeCharShifted[ kVK_ANSI_H ]='H'; + g_keycodeCharShifted[ kVK_ANSI_G ]='G'; + g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; + g_keycodeCharShifted[ kVK_ANSI_X ]='X'; + g_keycodeCharShifted[ kVK_ANSI_C ]='C'; + g_keycodeCharShifted[ kVK_ANSI_V ]='V'; + g_keycodeCharShifted[ kVK_ANSI_B ]='B'; + g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; + g_keycodeCharShifted[ kVK_ANSI_W ]='W'; + g_keycodeCharShifted[ kVK_ANSI_E ]='E'; + g_keycodeCharShifted[ kVK_ANSI_R ]='R'; + g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; + g_keycodeCharShifted[ kVK_ANSI_T ]='T'; + g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; + g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; + g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; + g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; + g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; + g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; + g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; + g_keycodeCharShifted[ kVK_ANSI_9 ]='('; + g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; + g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; + g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; + g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; + g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; + g_keycodeCharShifted[ kVK_ANSI_O ]='O'; + g_keycodeCharShifted[ kVK_ANSI_U ]='U'; + g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; + g_keycodeCharShifted[ kVK_ANSI_I ]='I'; + g_keycodeCharShifted[ kVK_ANSI_P ]='P'; + g_keycodeCharShifted[ kVK_ANSI_L ]='L'; + g_keycodeCharShifted[ kVK_ANSI_J ]='J'; + g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; + g_keycodeCharShifted[ kVK_ANSI_K ]='K'; + g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; + g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; + g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; + g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; + g_keycodeCharShifted[ kVK_ANSI_N ]='N'; + g_keycodeCharShifted[ kVK_ANSI_M ]='M'; + g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; + g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; + g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; + g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; + g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; + g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; + g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; + g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; + g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; + g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; + g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; + g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; + g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; + g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; + g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; + g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; + g_keycodeCharShifted[ kVK_Space ]=' '; +} + +- (void)setupImGuiHooks +{ + ImGuiIO &io = ImGui::GetIO(); + + [self setupKeymaps]; + + // Account for retina display for glScissor + g_displayScale = [[UIScreen mainScreen] scale]; + + ImGuiStyle &style = ImGui::GetStyle(); + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + + io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; + + UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; + [self.view addGestureRecognizer:panRecognizer]; + + UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; + [self.view addGestureRecognizer:tapRecoginzer]; + + // Fill out the Synergy key map + // (for some reason synergy scan codes are off by 1) + io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; + io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; + io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; + io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; + io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; + io.KeyMap[ImGuiKey_Home] = kVK_Home+1; + io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; + io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; + io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; + io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; + io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; + io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; + io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; + io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; + io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; +} + +- (void)connectServer: (NSString*)serverName +{ + self.serverName = serverName; + g_serverName = serverName; + + // Init synergy + NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; + + uSynergyInit( &_synergyCtx ); + _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); + _synergyCtx.m_clientWidth = self.view.bounds.size.width; + _synergyCtx.m_clientHeight = self.view.bounds.size.height; + + _synergyCtx.m_connectFunc = ImGui_ConnectFunc; + _synergyCtx.m_sendFunc = ImGui_SendFunc; + _synergyCtx.m_receiveFunc = ImGui_RecvFunc; + _synergyCtx.m_sleepFunc = ImGui_SleepFunc; + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; + + _synergyCtx.m_traceFunc = ImGui_TraceFunc; + _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; + _synergyCtx.m_mouseCallback = ImGui_MouseCallback; + _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; + + _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; + + // Create a background thread for synergy + _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); + dispatch_async( _synergyQueue, ^{ + while (1) { + uSynergyUpdate( &_synergyCtx ); + } + }); +} + + +- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer +{ + + if ((recognizer.state == UIGestureRecognizerStateBegan) || + (recognizer.state == UIGestureRecognizerStateChanged)) + { + _mouseDown = YES; + _touchPos = [recognizer locationInView:self.view]; + } + else + { + _mouseDown = NO; + _touchPos = CGPointMake( -1, -1 ); + } +} + +- (void)viewDidTap: (UITapGestureRecognizer*)recognizer +{ + _touchPos = [recognizer locationInView:self.view]; + _mouseTapped = YES; +} + +- (void)render +{ + ImGui::Render(); +} + +- (void)newFrame +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle &style = ImGui::GetStyle(); + + if (!g_FontTexture) + { + ImGui_ImplIOS_CreateDeviceObjects(); + } + + io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); + + io.MouseDrawCursor = g_synergyPtrActive; + if (g_synergyPtrActive) + { + style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); + io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); + for (int i=0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i]; + } + + // This is an arbitrary scaling factor that works for me. Not sure what units these + // mousewheel values from synergy are supposed to be in + io.MouseWheel = g_mouseWheelY / 500.0; + } + else + { + // Synergy not active, use touch events + style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); + io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); + if ((_mouseDown) || (_mouseTapped)) + { + io.MouseDown[0] = true; + _mouseTapped = NO; + } + else + { + io.MouseDown[0] = false; + } + } + + ImGui::NewFrame(); +} +@end + +// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// If text or lines are blurry when integrating ImGui in your engine: +// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) +// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES +static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled + GLint last_program, last_texture; + glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + // Setup orthographic projection matrix + const float width = ImGui::GetIO().DisplaySize.x; + const float height = ImGui::GetIO().DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/width, 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/-height, 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { -1.0f, 1.0f, 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); + glBindVertexArray(g_VaoHandle); + + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + ImDrawList* cmd_list = draw_data->CmdLists[n]; + ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); + + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); + if (g_VboSize < needed_vtx_size) + { + // Grow our buffer if needed + g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); + } + + unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); + if (!vtx_data) + continue; + memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) + { + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glScissor((int)(pcmd->ClipRect.x * g_displayScale), + (int)((height - pcmd->ClipRect.w) * g_displayScale), + (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), + (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); + glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); + } + idx_buffer += pcmd->ElemCount; + } + } + + // Restore modified state + glBindVertexArray(0); + glBindBuffer( GL_ARRAY_BUFFER, 0); + glEnable(GL_CULL_FACE); + glEnable(GL_DEPTH_TEST); + glUseProgram(last_program); + glDisable(GL_SCISSOR_TEST); + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +void ImGui_ImplIOS_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. + + // Upload texture to graphics system + GLint last_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); + glGenTextures(1, &g_FontTexture); + glBindTexture(GL_TEXTURE_2D, g_FontTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + + // Restore state + glBindTexture(GL_TEXTURE_2D, last_texture); +} + +bool ImGui_ImplIOS_CreateDeviceObjects() +{ + const GLchar *vertex_shader = + "uniform mat4 ProjMtx;\n" + "attribute highp vec2 Position;\n" + "attribute highp vec2 UV;\n" + "attribute highp vec4 Color;\n" + "varying vec2 Frag_UV;\n" + "varying vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " Frag_UV = UV;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + "}\n"; + + const GLchar* fragment_shader = + "uniform sampler2D Texture;\n" + "varying highp vec2 Frag_UV;\n" + "varying highp vec4 Frag_Color;\n" + "void main()\n" + "{\n" + " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" + "}\n"; + + g_ShaderHandle = glCreateProgram(); + g_VertHandle = glCreateShader(GL_VERTEX_SHADER); + g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_VertHandle, 1, &vertex_shader, 0); + glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glCompileShader(g_VertHandle); + +#if defined(DEBUG) + GLint logLength; + glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); + NSLog(@"VERTEX Shader compile log:\n%s", log); + free(log); + } +#endif + + glCompileShader(g_FragHandle); + +#if defined(DEBUG) + glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + GLchar *log = (GLchar *)malloc(logLength); + glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); + NSLog(@"FRAGMENT Shader compile log:\n%s", log); + free(log); + } +#endif + + glAttachShader(g_ShaderHandle, g_VertHandle); + glAttachShader(g_ShaderHandle, g_FragHandle); + glLinkProgram(g_ShaderHandle); + + g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); + g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); + g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); + g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); + g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); + + glGenBuffers(1, &g_VboHandle); + + glGenVertexArrays(1, &g_VaoHandle); + glBindVertexArray(g_VaoHandle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + +#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); +#undef OFFSETOF + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + ImGui_ImplIOS_CreateFontsTexture(); + + return true; +} diff --git a/examples/apple_example/imguiex-ios/main.m b/examples/apple_example/imguiex-ios/main.m new file mode 100644 index 0000000..faba099 --- /dev/null +++ b/examples/apple_example/imguiex-ios/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/examples/apple_example/imguiex-osx/AppDelegate.h b/examples/apple_example/imguiex-osx/AppDelegate.h new file mode 100644 index 0000000..33d199b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.h @@ -0,0 +1,15 @@ +// +// AppDelegate.h +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/examples/apple_example/imguiex-osx/AppDelegate.m b/examples/apple_example/imguiex-osx/AppDelegate.m new file mode 100644 index 0000000..59e877b --- /dev/null +++ b/examples/apple_example/imguiex-osx/AppDelegate.m @@ -0,0 +1,26 @@ +// +// AppDelegate.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@property (weak) IBOutlet NSWindow *window; +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + +@end diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..b13908f --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,64 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_imgui_180x180.png", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png new file mode 100644 index 0000000..f48b799 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/AppIcon.appiconset/icon_imgui_180x180.png Binary files differ diff --git a/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/examples/apple_example/imguiex-osx/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/examples/apple_example/imguiex-osx/Info.plist b/examples/apple_example/imguiex-osx/Info.plist new file mode 100644 index 0000000..ba1c2bb --- /dev/null +++ b/examples/apple_example/imguiex-osx/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2016 Joel Davis. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/examples/apple_example/imguiex-osx/main.m b/examples/apple_example/imguiex-osx/main.m new file mode 100644 index 0000000..20b0731 --- /dev/null +++ b/examples/apple_example/imguiex-osx/main.m @@ -0,0 +1,13 @@ +// +// main.m +// imguiex-osx +// +// Created by James Chen on 4/5/16. +// Copyright © 2016 Joel Davis. All rights reserved. +// + +#import + +int main(int argc, const char * argv[]) { + return NSApplicationMain(argc, argv); +} diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj new file mode 100644 index 0000000..652d15b --- /dev/null +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -0,0 +1,539 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F221CB39FB50090F036 /* AppDelegate.m */; }; + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A1A0F271CB39FB50090F036 /* Assets.xcassets */; }; + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; + 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-osx.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; + 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; + 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; + 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; + 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; + 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; + 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; + 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1A1A0F1C1CB39FB50090F036 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5511B2E632000C130BA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, + 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXGroup; + children = ( + 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F351CB3A1B20090F036 /* opengl_example */, + 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, + 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, + 1A1A0F271CB39FB50090F036 /* Assets.xcassets */, + 1A1A0F2C1CB39FB50090F036 /* Info.plist */, + 1A1A0F241CB39FB50090F036 /* Supporting Files */, + ); + path = "imguiex-osx"; + sourceTree = ""; + }; + 1A1A0F241CB39FB50090F036 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 1A1A0F351CB3A1B20090F036 /* opengl_example */ = { + isa = PBXGroup; + children = ( + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F391CB3A1B20090F036 /* main.cpp */, + ); + name = opengl_example; + path = ../../opengl_example; + sourceTree = ""; + }; + 6D1E39141B35EEF10017B40F /* usynergy */ = { + isa = PBXGroup; + children = ( + 6D1E39151B35EEF10017B40F /* uSynergy.c */, + 6D1E39161B35EEF10017B40F /* uSynergy.h */, + ); + name = usynergy; + path = ../libs/usynergy; + sourceTree = ""; + }; + 6D2FC54B1B2E632000C130BA = { + isa = PBXGroup; + children = ( + 6D1E39141B35EEF10017B40F /* usynergy */, + 6D2FC5841B2E648D00C130BA /* imgui */, + 6D2FC5561B2E632000C130BA /* imguiex-ios */, + 1A1A0F201CB39FB50090F036 /* imguiex-osx */, + 6D2FC5551B2E632000C130BA /* Products */, + ); + sourceTree = ""; + }; + 6D2FC5551B2E632000C130BA /* Products */ = { + isa = PBXGroup; + children = ( + 6D2FC5541B2E632000C130BA /* imguiex-ios.app */, + 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */, + ); + name = Products; + sourceTree = ""; + }; + 6D2FC5561B2E632000C130BA /* imguiex-ios */ = { + isa = PBXGroup; + children = ( + 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, + 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, + 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, + 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, + 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, + 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, + 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, + 6D2FC55E1B2E632000C130BA /* Shader.fsh */, + 6D2FC5601B2E632000C130BA /* Shader.vsh */, + 6D2FC5621B2E632000C130BA /* GameViewController.h */, + 6D2FC5631B2E632000C130BA /* GameViewController.m */, + 6D2FC5651B2E632000C130BA /* Main.storyboard */, + 6D2FC5681B2E632000C130BA /* Images.xcassets */, + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, + 6D2FC5571B2E632000C130BA /* Supporting Files */, + ); + path = "imguiex-ios"; + sourceTree = ""; + }; + 6D2FC5571B2E632000C130BA /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, + 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, + 6D2FC5581B2E632000C130BA /* Info.plist */, + 6D2FC5591B2E632000C130BA /* main.m */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 6D2FC5841B2E648D00C130BA /* imgui */ = { + isa = PBXGroup; + children = ( + 6D2FC5851B2E64AB00C130BA /* imconfig.h */, + 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, + 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, + 6D2FC5871B2E64AB00C130BA /* imgui.h */, + ); + name = imgui; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */; + buildPhases = ( + 1A1A0F1B1CB39FB50090F036 /* Sources */, + 1A1A0F1C1CB39FB50090F036 /* Frameworks */, + 1A1A0F1D1CB39FB50090F036 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-osx"; + productName = "imguiex-osx"; + productReference = 1A1A0F1F1CB39FB50090F036 /* imguiex-osx.app */; + productType = "com.apple.product-type.application"; + }; + 6D2FC5531B2E632000C130BA /* imguiex-ios */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */; + buildPhases = ( + 6D2FC5501B2E632000C130BA /* Sources */, + 6D2FC5511B2E632000C130BA /* Frameworks */, + 6D2FC5521B2E632000C130BA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "imguiex-ios"; + productName = imguiex; + productReference = 6D2FC5541B2E632000C130BA /* imguiex-ios.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6D2FC54C1B2E632000C130BA /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = "Joel Davis"; + TargetAttributes = { + 1A1A0F1E1CB39FB50090F036 = { + CreatedOnToolsVersion = 7.3; + }; + 6D2FC5531B2E632000C130BA = { + CreatedOnToolsVersion = 6.3.2; + }; + }; + }; + buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6D2FC54B1B2E632000C130BA; + productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6D2FC5531B2E632000C130BA /* imguiex-ios */, + 1A1A0F1E1CB39FB50090F036 /* imguiex-osx */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1A1A0F1D1CB39FB50090F036 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F281CB39FB50090F036 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5521B2E632000C130BA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, + 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, + 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, + 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, + 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1A1A0F1B1CB39FB50090F036 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1A1A0F301CB3A0DA0090F036 /* imgui_draw.cpp in Sources */, + 1A1A0F311CB3A0DA0090F036 /* imgui.cpp in Sources */, + 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */, + 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */, + 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, + 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, + 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6D2FC5501B2E632000C130BA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, + 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, + 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, + 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, + 6D2FC55A1B2E632000C130BA /* main.m in Sources */, + 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, + 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, + 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, + 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC5661B2E632000C130BA /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 6D2FC56B1B2E632000C130BA /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 1A1A0F2D1CB39FB50090F036 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 1A1A0F2E1CB39FB50090F036 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../../", + /usr/local/include, + ); + INFOPLIST_FILE = "imguiex-osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = /usr/local/lib; + MACOSX_DEPLOYMENT_TARGET = 10.11; + PRODUCT_BUNDLE_IDENTIFIER = "org.imgui.example.imguiex.imguiex-osx"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Release; + }; + 6D2FC5791B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + }; + name = Debug; + }; + 6D2FC57A1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + HEADER_SEARCH_PATHS = "$(SRCROOT)/../../"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6D2FC57C1B2E632000C130BA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 6D2FC57D1B2E632000C130BA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "imguiex-ios/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1A1A0F2F1CB39FB50090F036 /* Build configuration list for PBXNativeTarget "imguiex-osx" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1A1A0F2D1CB39FB50090F036 /* Debug */, + 1A1A0F2E1CB39FB50090F036 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC5791B2E632000C130BA /* Debug */, + 6D2FC57A1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex-ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6D2FC57C1B2E632000C130BA /* Debug */, + 6D2FC57D1B2E632000C130BA /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; +} diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 21f86f5..f0e57f7 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) { + ID3D10Device* ctx = g_pd3dDevice; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -58,7 +60,7 @@ desc.BindFlags = D3D10_BIND_VERTEX_BUFFER; desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVB) < 0) + if (ctx->CreateBuffer(&desc, NULL, &g_pVB) < 0) return; } @@ -66,13 +68,13 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D10_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D10_BUFFER_DESC)); - bufferDesc.Usage = D3D10_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D10_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D10_BUFFER_DESC)); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D10_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + if (ctx->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } @@ -81,7 +83,6 @@ ImDrawIdx* idx_dst = NULL; g_pVB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&vtx_dst); g_pIB->Map(D3D10_MAP_WRITE_DISCARD, 0, (void**)&idx_dst); - for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -95,11 +96,10 @@ // Setup orthographic projection matrix into our constant buffer { - void* mappedResource; - if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + void* mapped_resource; + if (g_pVertexConstantBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource; + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource; const float L = 0.0f; const float R = ImGui::GetIO().DisplaySize.x; const float B = ImGui::GetIO().DisplaySize.y; @@ -111,39 +111,72 @@ { 0.0f, 0.0f, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); g_pVertexConstantBuffer->Unmap(); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX10_STATE { - D3D10_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D10_VIEWPORT)); - vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; - vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDevice->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D10_RECT ScissorRects[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D10_VIEWPORT Viewports[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D10RasterizerState* RS; + ID3D10BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D10ShaderResourceView* PSShaderResource; + ID3D10SamplerState* PSSampler; + ID3D10PixelShader* PS; + ID3D10VertexShader* VS; + D3D10_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D10Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D10InputLayout* InputLayout; + }; + BACKUP_DX10_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + ctx->PSGetShader(&old.PS); + ctx->VSGetShader(&old.VS); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D10_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D10_VIEWPORT)); + vp.Width = (UINT)ImGui::GetIO().DisplaySize.x; + vp.Height = (UINT)ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDevice->IASetInputLayout(g_pInputLayout); - g_pd3dDevice->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDevice->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDevice->VSSetShader(g_pVertexShader); - g_pd3dDevice->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDevice->PSSetShader(g_pPixelShader); - g_pd3dDevice->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDevice->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDevice->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -161,19 +194,29 @@ else { const D3D10_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDevice->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); - g_pd3dDevice->RSSetScissorRects(1, &r); - g_pd3dDevice->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D10ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDevice->IASetInputLayout(NULL); - g_pd3dDevice->PSSetShader(NULL); - g_pd3dDevice->VSSetShader(NULL); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS); if (old.PS) old.PS->Release(); + ctx->VSSetShader(old.VS); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,33 +277,33 @@ // Create DX10 texture { - D3D10_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D10_USAGE_DEFAULT; - texDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DEFAULT; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D10Texture2D *pTexture = NULL; D3D10_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; + ZeroMemory(&srv_desc, sizeof(srv_desc)); + srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srv_desc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = desc.MipLevels; + srv_desc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srv_desc, &g_pFontTextureView); pTexture->Release(); } @@ -269,17 +312,17 @@ // Create texture sampler { - D3D10_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D10_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D10_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D10_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D10_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } // Cleanup (don't clear the input data if you want to append new fonts later) @@ -331,24 +374,24 @@ return false; // Create the input layout - D3D10_INPUT_ELEMENT_DESC localLayout[] = { + D3D10_INPUT_ELEMENT_DESC local_layout[] = + { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D10_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D10_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D10_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 8451fb8..5f209bc 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -46,6 +46,8 @@ // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) { + ID3D11DeviceContext* ctx = g_pd3dDeviceContext; + // Create and grow vertex/index buffers if needed if (!g_pVB || g_VertexBufferSize < draw_data->TotalVtxCount) { @@ -65,21 +67,21 @@ { if (g_pIB) { g_pIB->Release(); g_pIB = NULL; } g_IndexBufferSize = draw_data->TotalIdxCount + 10000; - D3D11_BUFFER_DESC bufferDesc; - memset(&bufferDesc, 0, sizeof(D3D11_BUFFER_DESC)); - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - if (g_pd3dDevice->CreateBuffer(&bufferDesc, NULL, &g_pIB) < 0) + D3D11_BUFFER_DESC desc; + memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.ByteWidth = g_IndexBufferSize * sizeof(ImDrawIdx); + desc.BindFlags = D3D11_BIND_INDEX_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + if (g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pIB) < 0) return; } // Copy and convert all vertices into a single contiguous buffer D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; - if (g_pd3dDeviceContext->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) + if (ctx->Map(g_pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) return; - if (g_pd3dDeviceContext->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) + if (ctx->Map(g_pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) return; ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; @@ -91,60 +93,95 @@ vtx_dst += cmd_list->VtxBuffer.size(); idx_dst += cmd_list->IdxBuffer.size(); } - g_pd3dDeviceContext->Unmap(g_pVB, 0); - g_pd3dDeviceContext->Unmap(g_pIB, 0); + ctx->Unmap(g_pVB, 0); + ctx->Unmap(g_pIB, 0); // Setup orthographic projection matrix into our constant buffer { - D3D11_MAPPED_SUBRESOURCE mappedResource; - if (g_pd3dDeviceContext->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource) != S_OK) + D3D11_MAPPED_SUBRESOURCE mapped_resource; + if (ctx->Map(g_pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) return; - - VERTEX_CONSTANT_BUFFER* pConstantBuffer = (VERTEX_CONSTANT_BUFFER*)mappedResource.pData; - const float L = 0.0f; - const float R = ImGui::GetIO().DisplaySize.x; - const float B = ImGui::GetIO().DisplaySize.y; - const float T = 0.0f; - const float mvp[4][4] = + VERTEX_CONSTANT_BUFFER* constant_buffer = (VERTEX_CONSTANT_BUFFER*)mapped_resource.pData; + float L = 0.0f; + float R = ImGui::GetIO().DisplaySize.x; + float B = ImGui::GetIO().DisplaySize.y; + float T = 0.0f; + float mvp[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, 0.5f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, }; - memcpy(&pConstantBuffer->mvp, mvp, sizeof(mvp)); - g_pd3dDeviceContext->Unmap(g_pVertexConstantBuffer, 0); + memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); + ctx->Unmap(g_pVertexConstantBuffer, 0); } - // Setup viewport + // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) + struct BACKUP_DX11_STATE { - D3D11_VIEWPORT vp; - memset(&vp, 0, sizeof(D3D11_VIEWPORT)); - vp.Width = ImGui::GetIO().DisplaySize.x; - vp.Height = ImGui::GetIO().DisplaySize.y; - vp.MinDepth = 0.0f; - vp.MaxDepth = 1.0f; - vp.TopLeftX = 0; - vp.TopLeftY = 0; - g_pd3dDeviceContext->RSSetViewports(1, &vp); - } + UINT ScissorRectsCount, ViewportsCount; + D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; + ID3D11RasterizerState* RS; + ID3D11BlendState* BlendState; + FLOAT BlendFactor[4]; + UINT SampleMask; + ID3D11ShaderResourceView* PSShaderResource; + ID3D11SamplerState* PSSampler; + ID3D11PixelShader* PS; + ID3D11VertexShader* VS; + UINT PSInstancesCount, VSInstancesCount; + ID3D11ClassInstance* PSInstances[256], *VSInstances[256]; // 256 is max according to PSSetShader documentation + D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; + ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; + UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; + DXGI_FORMAT IndexBufferFormat; + ID3D11InputLayout* InputLayout; + }; + BACKUP_DX11_STATE old; + old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); + ctx->RSGetViewports(&old.ViewportsCount, old.Viewports); + ctx->RSGetState(&old.RS); + ctx->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); + ctx->PSGetShaderResources(0, 1, &old.PSShaderResource); + ctx->PSGetSamplers(0, 1, &old.PSSampler); + old.PSInstancesCount = old.VSInstancesCount = 256; + ctx->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); + ctx->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); + ctx->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); + ctx->IAGetPrimitiveTopology(&old.PrimitiveTopology); + ctx->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); + ctx->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); + ctx->IAGetInputLayout(&old.InputLayout); + + // Setup viewport + D3D11_VIEWPORT vp; + memset(&vp, 0, sizeof(D3D11_VIEWPORT)); + vp.Width = ImGui::GetIO().DisplaySize.x; + vp.Height = ImGui::GetIO().DisplaySize.y; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = vp.TopLeftY = 0.0f; + ctx->RSSetViewports(1, &vp); // Bind shader and vertex buffers unsigned int stride = sizeof(ImDrawVert); unsigned int offset = 0; - g_pd3dDeviceContext->IASetInputLayout(g_pInputLayout); - g_pd3dDeviceContext->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); - g_pd3dDeviceContext->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); - g_pd3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - g_pd3dDeviceContext->VSSetShader(g_pVertexShader, NULL, 0); - g_pd3dDeviceContext->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); - g_pd3dDeviceContext->PSSetShader(g_pPixelShader, NULL, 0); - g_pd3dDeviceContext->PSSetSamplers(0, 1, &g_pFontSampler); + ctx->IASetInputLayout(g_pInputLayout); + ctx->IASetVertexBuffers(0, 1, &g_pVB, &stride, &offset); + ctx->IASetIndexBuffer(g_pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ctx->VSSetShader(g_pVertexShader, NULL, 0); + ctx->VSSetConstantBuffers(0, 1, &g_pVertexConstantBuffer); + ctx->PSSetShader(g_pPixelShader, NULL, 0); + ctx->PSSetSamplers(0, 1, &g_pFontSampler); // Setup render state - const float blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; - g_pd3dDeviceContext->OMSetBlendState(g_pBlendState, blendFactor, 0xffffffff); - g_pd3dDeviceContext->RSSetState(g_pRasterizerState); + const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; + ctx->OMSetBlendState(g_pBlendState, blend_factor, 0xffffffff); + ctx->RSSetState(g_pRasterizerState); // Render command lists int vtx_offset = 0; @@ -162,19 +199,31 @@ else { const D3D11_RECT r = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; - g_pd3dDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); - g_pd3dDeviceContext->RSSetScissorRects(1, &r); - g_pd3dDeviceContext->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); + ctx->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView**)&pcmd->TextureId); + ctx->RSSetScissorRects(1, &r); + ctx->DrawIndexed(pcmd->ElemCount, idx_offset, vtx_offset); } idx_offset += pcmd->ElemCount; } vtx_offset += cmd_list->VtxBuffer.size(); } - // Restore modified state - g_pd3dDeviceContext->IASetInputLayout(NULL); - g_pd3dDeviceContext->PSSetShader(NULL, NULL, 0); - g_pd3dDeviceContext->VSSetShader(NULL, NULL, 0); + // Restore modified DX state + ctx->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); + ctx->RSSetViewports(old.ViewportsCount, old.Viewports); + ctx->RSSetState(old.RS); if (old.RS) old.RS->Release(); + ctx->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); + ctx->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); + ctx->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); + ctx->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); + for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); + ctx->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); + ctx->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); + for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); + ctx->IASetPrimitiveTopology(old.PrimitiveTopology); + ctx->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); + ctx->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); + ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) @@ -234,31 +283,31 @@ // Upload texture to graphics system { - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = 0; ID3D11Texture2D *pTexture = NULL; D3D11_SUBRESOURCE_DATA subResource; subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemPitch = desc.Width * 4; subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); // Create texture view D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(srvDesc)); srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MipLevels = desc.MipLevels; srvDesc.Texture2D.MostDetailedMip = 0; g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); pTexture->Release(); @@ -269,17 +318,17 @@ // Create texture sampler { - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + D3D11_SAMPLER_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + desc.MipLODBias = 0.f; + desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + desc.MinLOD = 0.f; + desc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } } @@ -327,24 +376,23 @@ return false; // Create the input layout - D3D11_INPUT_ELEMENT_DESC localLayout[] = { + D3D11_INPUT_ELEMENT_DESC local_layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - - if (g_pd3dDevice->CreateInputLayout(localLayout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) + if (g_pd3dDevice->CreateInputLayout(local_layout, 3, g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize(), &g_pInputLayout) != S_OK) return false; // Create the constant buffer { - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); - cbDesc.Usage = D3D11_USAGE_DYNAMIC; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - cbDesc.MiscFlags = 0; - g_pd3dDevice->CreateBuffer(&cbDesc, NULL, &g_pVertexConstantBuffer); + D3D11_BUFFER_DESC desc; + desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER); + desc.Usage = D3D11_USAGE_DYNAMIC; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + g_pd3dDevice->CreateBuffer(&desc, NULL, &g_pVertexConstantBuffer); } } diff --git a/examples/ios_example/.gitignore b/examples/ios_example/.gitignore deleted file mode 100644 index 8feda89..0000000 --- a/examples/ios_example/.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/ios_example/README.md b/examples/ios_example/README.md deleted file mode 100644 index a2ada95..0000000 --- a/examples/ios_example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# iOS example - -## Introduction - -This example is the default XCode "OpenGL" example code, modified to support ImGui and [Synergy](http://synergy-project.org/). - -It is a rather complex example because of all of the faff required to get an XCode/iOS application running. Refer to the regular OpenGL examples if you want to learn about integrating ImGui. - -Synergy (remote keyboard/mouse) is not required, but it's pretty hard to use ImGui without it. Synergy includes a "uSynergy" library that allows embedding a synergy client, this is what is used here. ImGui supports "TouchPadding", and this is enabled when Synergy is not active. - -## How to Use - -0. In Synergy, go to Preferences, and uncheck "Use SSL encryption" -0. Run the example app. -0. Tap the "servername" button in the corner -0. Enter the name or the IP of your synergy host -0. If you had previously connected to a server, you may need to kill and re-start the app. - -## Notes and TODOs - -Things that would be nice but I didn't get around to doing: - -* iOS software keyboard not supported for text inputs -* iOS hardware (bluetooth) keyboards not supported -* Graceful disconnect/reconnect from uSynergy. -* Copy/Paste not well-supported - -## C++ on iOS -ImGui is a c++ library. If you want to include it directly, rename your Obj-C file to have the ".mm" extension. - -Alternatively, you can wrap your debug code in a C interface, this is what I am demonstrating here with the "debug_hud.h" interface. Either approach works, use whatever you prefer. - -In my case, most of my game code is already in C++ so it's not really an issue and I can use ImGui directly. diff --git a/examples/ios_example/imguiex.xcodeproj/project.pbxproj b/examples/ios_example/imguiex.xcodeproj/project.pbxproj deleted file mode 100644 index 26bcff4..0000000 --- a/examples/ios_example/imguiex.xcodeproj/project.pbxproj +++ /dev/null @@ -1,373 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */; }; - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; - 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC55E1B2E632000C130BA /* Shader.fsh */; }; - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5601B2E632000C130BA /* Shader.vsh */; }; - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5631B2E632000C130BA /* GameViewController.m */; }; - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5651B2E632000C130BA /* Main.storyboard */; }; - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC5681B2E632000C130BA /* Images.xcassets */; }; - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */; }; - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */; }; - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5861B2E64AB00C130BA /* imgui.cpp */; }; - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5901B30773F00C130BA /* CFNetwork.framework */; }; - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_draw.cpp; path = ../../imgui_draw.cpp; sourceTree = ""; }; - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_demo.cpp; path = ../../../imgui_demo.cpp; sourceTree = ""; }; - 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; - 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; - 6D2FC5541B2E632000C130BA /* imguiex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = imguiex.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D2FC5581B2E632000C130BA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 6D2FC5591B2E632000C130BA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 6D2FC55E1B2E632000C130BA /* Shader.fsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.fsh; path = Shaders/Shader.fsh; sourceTree = ""; }; - 6D2FC5601B2E632000C130BA /* Shader.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = Shader.vsh; path = Shaders/Shader.vsh; sourceTree = ""; }; - 6D2FC5621B2E632000C130BA /* GameViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GameViewController.h; sourceTree = ""; }; - 6D2FC5631B2E632000C130BA /* GameViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GameViewController.m; sourceTree = ""; }; - 6D2FC5661B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 6D2FC5681B2E632000C130BA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 6D2FC56B1B2E632000C130BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = imgui_impl_ios.mm; sourceTree = ""; }; - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_ios.h; sourceTree = ""; }; - 6D2FC5851B2E64AB00C130BA /* imconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imconfig.h; path = ../../imconfig.h; sourceTree = ""; }; - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui.cpp; path = ../../imgui.cpp; sourceTree = ""; }; - 6D2FC5871B2E64AB00C130BA /* imgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui.h; path = ../../imgui.h; sourceTree = ""; }; - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug_hud.cpp; sourceTree = ""; }; - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug_hud.h; sourceTree = ""; }; - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 6D2FC5511B2E632000C130BA /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC5931B30774900C130BA /* SystemConfiguration.framework in Frameworks */, - 6D2FC5911B30773F00C130BA /* CFNetwork.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 6D1E39141B35EEF10017B40F /* usynergy */ = { - isa = PBXGroup; - children = ( - 6D1E39151B35EEF10017B40F /* uSynergy.c */, - 6D1E39161B35EEF10017B40F /* uSynergy.h */, - ); - name = usynergy; - path = ../libs/usynergy; - sourceTree = ""; - }; - 6D2FC54B1B2E632000C130BA = { - isa = PBXGroup; - children = ( - 6D1E39141B35EEF10017B40F /* usynergy */, - 6D2FC5841B2E648D00C130BA /* imgui */, - 6D2FC5561B2E632000C130BA /* imguiex */, - 6D2FC5551B2E632000C130BA /* Products */, - ); - sourceTree = ""; - }; - 6D2FC5551B2E632000C130BA /* Products */ = { - isa = PBXGroup; - children = ( - 6D2FC5541B2E632000C130BA /* imguiex.app */, - ); - name = Products; - sourceTree = ""; - }; - 6D2FC5561B2E632000C130BA /* imguiex */ = { - isa = PBXGroup; - children = ( - 6D2FC5811B2E63A100C130BA /* imgui_impl_ios.mm */, - 6D2FC5821B2E63A100C130BA /* imgui_impl_ios.h */, - 197E1E881B89443600E3FE6A /* imgui_demo.cpp */, - 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */, - 6D2FC58A1B2E6A5500C130BA /* debug_hud.h */, - 6D2FC55B1B2E632000C130BA /* AppDelegate.h */, - 6D2FC55C1B2E632000C130BA /* AppDelegate.m */, - 6D2FC55E1B2E632000C130BA /* Shader.fsh */, - 6D2FC5601B2E632000C130BA /* Shader.vsh */, - 6D2FC5621B2E632000C130BA /* GameViewController.h */, - 6D2FC5631B2E632000C130BA /* GameViewController.m */, - 6D2FC5651B2E632000C130BA /* Main.storyboard */, - 6D2FC5681B2E632000C130BA /* Images.xcassets */, - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */, - 6D2FC5571B2E632000C130BA /* Supporting Files */, - ); - path = imguiex; - sourceTree = ""; - }; - 6D2FC5571B2E632000C130BA /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 6D2FC5921B30774900C130BA /* SystemConfiguration.framework */, - 6D2FC5901B30773F00C130BA /* CFNetwork.framework */, - 6D2FC5581B2E632000C130BA /* Info.plist */, - 6D2FC5591B2E632000C130BA /* main.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 6D2FC5841B2E648D00C130BA /* imgui */ = { - isa = PBXGroup; - children = ( - 6D2FC5851B2E64AB00C130BA /* imconfig.h */, - 197E1E861B8943FE00E3FE6A /* imgui_draw.cpp */, - 6D2FC5861B2E64AB00C130BA /* imgui.cpp */, - 6D2FC5871B2E64AB00C130BA /* imgui.h */, - ); - name = imgui; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 6D2FC5531B2E632000C130BA /* imguiex */ = { - isa = PBXNativeTarget; - buildConfigurationList = 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */; - buildPhases = ( - 6D2FC5501B2E632000C130BA /* Sources */, - 6D2FC5511B2E632000C130BA /* Frameworks */, - 6D2FC5521B2E632000C130BA /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = imguiex; - productName = imguiex; - productReference = 6D2FC5541B2E632000C130BA /* imguiex.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 6D2FC54C1B2E632000C130BA /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0630; - ORGANIZATIONNAME = "Joel Davis"; - TargetAttributes = { - 6D2FC5531B2E632000C130BA = { - CreatedOnToolsVersion = 6.3.2; - }; - }; - }; - buildConfigurationList = 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 6D2FC54B1B2E632000C130BA; - productRefGroup = 6D2FC5551B2E632000C130BA /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 6D2FC5531B2E632000C130BA /* imguiex */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 6D2FC5521B2E632000C130BA /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC56C1B2E632000C130BA /* LaunchScreen.xib in Resources */, - 6D2FC5671B2E632000C130BA /* Main.storyboard in Resources */, - 6D2FC5691B2E632000C130BA /* Images.xcassets in Resources */, - 6D2FC5611B2E632000C130BA /* Shader.vsh in Resources */, - 6D2FC55F1B2E632000C130BA /* Shader.fsh in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 6D2FC5501B2E632000C130BA /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */, - 6D2FC5831B2E63A100C130BA /* imgui_impl_ios.mm in Sources */, - 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */, - 6D2FC5641B2E632000C130BA /* GameViewController.m in Sources */, - 6D2FC55A1B2E632000C130BA /* main.m in Sources */, - 6D2FC5881B2E64AB00C130BA /* imgui.cpp in Sources */, - 6D2FC58B1B2E6A5500C130BA /* debug_hud.cpp in Sources */, - 197E1E871B8943FE00E3FE6A /* imgui_draw.cpp in Sources */, - 197E1E891B89443600E3FE6A /* imgui_demo.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 6D2FC5651B2E632000C130BA /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC5661B2E632000C130BA /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 6D2FC56A1B2E632000C130BA /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 6D2FC56B1B2E632000C130BA /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 6D2FC5791B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 6D2FC57A1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - 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; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 6D2FC57C1B2E632000C130BA /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 6D2FC57D1B2E632000C130BA /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - INFOPLIST_FILE = imguiex/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 6D2FC54F1B2E632000C130BA /* Build configuration list for PBXProject "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC5791B2E632000C130BA /* Debug */, - 6D2FC57A1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 6D2FC57B1B2E632000C130BA /* Build configuration list for PBXNativeTarget "imguiex" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 6D2FC57C1B2E632000C130BA /* Debug */, - 6D2FC57D1B2E632000C130BA /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 6D2FC54C1B2E632000C130BA /* Project object */; -} diff --git a/examples/ios_example/imguiex/AppDelegate.h b/examples/ios_example/imguiex/AppDelegate.h deleted file mode 100644 index 82f1542..0000000 --- a/examples/ios_example/imguiex/AppDelegate.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// AppDelegate.h -// imguiex - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/examples/ios_example/imguiex/AppDelegate.m b/examples/ios_example/imguiex/AppDelegate.m deleted file mode 100644 index ab83101..0000000 --- a/examples/ios_example/imguiex/AppDelegate.m +++ /dev/null @@ -1,41 +0,0 @@ -// -// AppDelegate.m -// imguiex - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib b/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 5717c00..0000000 --- a/examples/ios_example/imguiex/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/Base.lproj/Main.storyboard b/examples/ios_example/imguiex/Base.lproj/Main.storyboard deleted file mode 100644 index 90dfb2e..0000000 --- a/examples/ios_example/imguiex/Base.lproj/Main.storyboard +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/ios_example/imguiex/GameViewController.h b/examples/ios_example/imguiex/GameViewController.h deleted file mode 100644 index 3323cfd..0000000 --- a/examples/ios_example/imguiex/GameViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// GameViewController.h -// imguiex - -// This is the OpenGL Example template from XCode, modified to support ImGui - -#import -#import - -@interface GameViewController : GLKViewController - -@end diff --git a/examples/ios_example/imguiex/GameViewController.m b/examples/ios_example/imguiex/GameViewController.m deleted file mode 100644 index e902f7a..0000000 --- a/examples/ios_example/imguiex/GameViewController.m +++ /dev/null @@ -1,481 +0,0 @@ -// -// GameViewController.m -// imguiex -// -#import "GameViewController.h" -#import - -#import "imgui_impl_ios.h" -#import "debug_hud.h" - -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) - -#define SERVERNAME_KEY @"ServerName" - -#define SERVERNAME_ALERT_TAG (10) - -// Uniform index. -enum -{ - UNIFORM_MODELVIEWPROJECTION_MATRIX, - UNIFORM_NORMAL_MATRIX, - UNIFORM_DIFFUSE_COLOR, - - NUM_UNIFORMS -}; -GLint uniforms[NUM_UNIFORMS]; - -// Attribute index. -enum -{ - ATTRIB_VERTEX, - ATTRIB_NORMAL, - NUM_ATTRIBUTES -}; - -GLfloat gCubeVertexData[216] = -{ - // Data layout for each line below is: - // positionX, positionY, positionZ, normalX, normalY, normalZ, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f -}; - -@interface GameViewController () -{ - GLuint _program; - - GLKMatrix4 _modelViewProjectionMatrix; - GLKMatrix3 _normalMatrix; - float _rotation; - - GLuint _vertexArray; - GLuint _vertexBuffer; - - DebugHUD _hud; -} -@property (strong, nonatomic) EAGLContext *context; -@property (strong, nonatomic) GLKBaseEffect *effect; -@property (strong, nonatomic) ImGuiHelper *imgui; -@property (weak, nonatomic) IBOutlet UIButton *btnServername; - -@property (strong, nonatomic) NSString *serverName; - -- (IBAction)onServernameTapped:(id)sender; - -- (void)setupGL; -- (void)tearDownGL; - -- (BOOL)loadShaders; -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file; -- (BOOL)linkProgram:(GLuint)prog; -- (BOOL)validateProgram:(GLuint)prog; -@end - -@implementation GameViewController - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - - if (!self.context) { - NSLog(@"Failed to create ES context"); - } - - GLKView *view = (GLKView *)self.view; - view.context = self.context; - view.drawableDepthFormat = GLKViewDrawableDepthFormat24; - - [self.btnServername setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - - [self setupGL]; - - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - self.serverName = [userDefaults objectForKey: SERVERNAME_KEY ]; - self.imgui = [[ImGuiHelper alloc] initWithView:self.view ]; - if (self.serverName) - { - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - [self.imgui connectServer: self.serverName ]; - } - - DebugHUD_InitDefaults( &_hud ); -} - -- (void)dealloc -{ - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - - if ([self isViewLoaded] && ([[self view] window] == nil)) { - self.view = nil; - - [self tearDownGL]; - - if ([EAGLContext currentContext] == self.context) { - [EAGLContext setCurrentContext:nil]; - } - self.context = nil; - } - - // Dispose of any resources that can be recreated. -} - - -- (BOOL)prefersStatusBarHidden { - return YES; -} - -- (IBAction)onServernameTapped:(id)sender -{ - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Set Server" message:@"Enter server name or IP for uSynergy" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Cancel", nil ]; - alert.alertViewStyle = UIAlertViewStylePlainTextInput; - alert.tag = SERVERNAME_ALERT_TAG; // cheezy way to tell which alert view we're responding to - [alert show]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex -{ - if ((buttonIndex==0)&&(alertView.tag==SERVERNAME_ALERT_TAG)) - { - // This is really janky. I usually just hardcode the servername since I'm building it anyway. - // If you want to properly handle updating the server, you'll want to tear down and recreate - // the usynergy stuff in connectServer - BOOL serverNameWasSet = self.serverName.length > 0; - NSString *serverName = [[alertView textFieldAtIndex:0] text]; - - if ([serverName length] > 0) { - self.serverName = serverName; - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setObject:serverName forKey:SERVERNAME_KEY ]; - [userDefaults synchronize]; - - [self.btnServername setTitle:self.serverName forState:UIControlStateNormal]; - - // If we hadn't previously connected, try now - if (!serverNameWasSet) { - [self.imgui connectServer:self.serverName]; - } - else - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Servername Updated" - message:@"Restart the app to connect the server" - delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; - [alert show]; - } - } - } -} - -- (void)setupGL -{ - [EAGLContext setCurrentContext:self.context]; - - [self loadShaders]; - - self.effect = [[GLKBaseEffect alloc] init]; - self.effect.light0.enabled = GL_TRUE; - self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.4f, 0.4f, 1.0f); - - glEnable(GL_DEPTH_TEST); - - glGenVertexArraysOES(1, &_vertexArray); - glBindVertexArrayOES(_vertexArray); - - glGenBuffers(1, &_vertexBuffer); - glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW); - - glEnableVertexAttribArray(GLKVertexAttribPosition); - glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(GLKVertexAttribNormal); - glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12)); - - glBindVertexArrayOES(0); - - -} - -- (void)tearDownGL -{ - [EAGLContext setCurrentContext:self.context]; - - glDeleteBuffers(1, &_vertexBuffer); - glDeleteVertexArraysOES(1, &_vertexArray); - - self.effect = nil; - - if (_program) { - glDeleteProgram(_program); - _program = 0; - } -} - -#pragma mark - GLKView and GLKViewController delegate methods - -- (void)update -{ - float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); - GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f); - - self.effect.transform.projectionMatrix = projectionMatrix; - - GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f); - baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f); - - // Compute the model view matrix for the object rendered with GLKit - GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - self.effect.transform.modelviewMatrix = modelViewMatrix; - - // Compute the model view matrix for the object rendered with ES2 - modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 1.5f); - modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f); - modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix); - - _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); - - _modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix); - - _rotation += self.timeSinceLastUpdate * (_hud.rotation_speed * (M_PI / 180.0)); -} - - -- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect -{ - glClearColor(0.65f, 0.65f, 0.65f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glBindVertexArrayOES(_vertexArray); - - // Render the object with GLKit - [self.effect prepareToDraw]; - - glDrawArrays(GL_TRIANGLES, 0, 36); - - // Render the object again with ES2 - glUseProgram(_program); - - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); - glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); - glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - - self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - - // Now render Imgui - [self.imgui render]; - -} - -#pragma mark - OpenGL ES 2 shader compilation - -- (BOOL)loadShaders -{ - GLuint vertShader, fragShader; - NSString *vertShaderPathname, *fragShaderPathname; - - // Create shader program. - _program = glCreateProgram(); - - // Create and compile vertex shader. - vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"]; - if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) { - NSLog(@"Failed to compile vertex shader"); - return NO; - } - - // Create and compile fragment shader. - fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"]; - if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) { - NSLog(@"Failed to compile fragment shader"); - return NO; - } - - // Attach vertex shader to program. - glAttachShader(_program, vertShader); - - // Attach fragment shader to program. - glAttachShader(_program, fragShader); - - // Bind attribute locations. - // This needs to be done prior to linking. - glBindAttribLocation(_program, GLKVertexAttribPosition, "position"); - glBindAttribLocation(_program, GLKVertexAttribNormal, "normal"); - - // Link program. - if (![self linkProgram:_program]) { - NSLog(@"Failed to link program: %d", _program); - - if (vertShader) { - glDeleteShader(vertShader); - vertShader = 0; - } - if (fragShader) { - glDeleteShader(fragShader); - fragShader = 0; - } - if (_program) { - glDeleteProgram(_program); - _program = 0; - } - - return NO; - } - - // Get uniform locations. - uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix"); - uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix"); - uniforms[UNIFORM_DIFFUSE_COLOR] = glGetUniformLocation(_program, "diffuseColor"); - - // Release vertex and fragment shaders. - if (vertShader) { - glDetachShader(_program, vertShader); - glDeleteShader(vertShader); - } - if (fragShader) { - glDetachShader(_program, fragShader); - glDeleteShader(fragShader); - } - - return YES; -} - -- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file -{ - GLint status; - const GLchar *source; - - source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String]; - if (!source) { - NSLog(@"Failed to load vertex shader"); - return NO; - } - - *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); - glCompileShader(*shader); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(*shader, logLength, &logLength, log); - NSLog(@"Shader compile log:\n%s", log); - free(log); - } -#endif - - glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); - if (status == 0) { - glDeleteShader(*shader); - return NO; - } - - return YES; -} - -- (BOOL)linkProgram:(GLuint)prog -{ - GLint status; - glLinkProgram(prog); - -#if defined(DEBUG) - GLint logLength; - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program link log:\n%s", log); - free(log); - } -#endif - - glGetProgramiv(prog, GL_LINK_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -- (BOOL)validateProgram:(GLuint)prog -{ - GLint logLength, status; - - glValidateProgram(prog); - glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetProgramInfoLog(prog, logLength, &logLength, log); - NSLog(@"Program validate log:\n%s", log); - free(log); - } - - glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); - if (status == 0) { - return NO; - } - - return YES; -} - -@end diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index a05a29b..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@2x~iphone.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "icon_imgui_60@3x~iphone.png", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76~ipad.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "icon_imgui_76@2x~ipad.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png deleted file mode 100644 index d728bc3..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@2x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png deleted file mode 100644 index f48b799..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_60@3x~iphone.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png deleted file mode 100644 index 67b08b8..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76@2x~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png b/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png deleted file mode 100644 index ae88e04..0000000 --- a/examples/ios_example/imguiex/Images.xcassets/AppIcon.appiconset/icon_imgui_76~ipad.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/Info.plist b/examples/ios_example/imguiex/Info.plist deleted file mode 100644 index bc6f548..0000000 --- a/examples/ios_example/imguiex/Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.imgui.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/examples/ios_example/imguiex/Shaders/Shader.fsh b/examples/ios_example/imguiex/Shaders/Shader.fsh deleted file mode 100644 index 4000524..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.fsh +++ /dev/null @@ -1,10 +0,0 @@ -// -// Shader.fsh -// imguiex - -varying lowp vec4 colorVarying; - -void main() -{ - gl_FragColor = colorVarying; -} diff --git a/examples/ios_example/imguiex/Shaders/Shader.vsh b/examples/ios_example/imguiex/Shaders/Shader.vsh deleted file mode 100644 index 313c3d7..0000000 --- a/examples/ios_example/imguiex/Shaders/Shader.vsh +++ /dev/null @@ -1,25 +0,0 @@ -// -// Shader.vsh -// imguiex - -attribute vec4 position; -attribute vec3 normal; - -varying lowp vec4 colorVarying; - -uniform vec3 diffuseColor; -uniform mat4 modelViewProjectionMatrix; -uniform mat3 normalMatrix; - -void main() -{ - vec3 eyeNormal = normalize(normalMatrix * normal); - vec3 lightPosition = vec3(0.0, 0.0, 1.0); - - float nDotVP = max(0.0, dot(eyeNormal, normalize(lightPosition))); - - vec3 colorLit = diffuseColor * nDotVP; - colorVarying = vec4( colorLit.x, colorLit.y, colorLit.z, 1.0 ); - - gl_Position = modelViewProjectionMatrix * position; -} diff --git a/examples/ios_example/imguiex/debug_hud.cpp b/examples/ios_example/imguiex/debug_hud.cpp deleted file mode 100644 index c75938a..0000000 --- a/examples/ios_example/imguiex/debug_hud.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// debug_hud.cpp -// imguiex - -#include - -#include "debug_hud.h" -#include "imgui.h" - -void DebugHUD_InitDefaults( DebugHUD *hud ) -{ - hud->show_test_window = true; - hud->show_example_window = true; - hud->rotation_speed = 15.0f; - - hud->cubeColor1[0] = 0.4f; - hud->cubeColor1[1] = 0.4f; - hud->cubeColor1[2] = 1.0f; - hud->cubeColor1[3] = 1.0f; - - hud->cubeColor2[0] = 1.0f; - hud->cubeColor2[1] = 0.4f; - hud->cubeColor2[2] = 0.4f; - hud->cubeColor2[3] = 1.0f; -} - -void DebugHUD_DoInterface( DebugHUD *hud ) -{ - if (hud->show_test_window) - { - ImGui::SetNextWindowPos( ImVec2( 400, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::ShowTestWindow( &hud->show_test_window ); - } - - if (hud->show_example_window) - { - ImGui::SetNextWindowPos( ImVec2( 20, 20 ), ImGuiSetCond_FirstUseEver ); - ImGui::SetNextWindowSize( ImVec2( 350, 200 ), ImGuiSetCond_FirstUseEver ); - ImGui::Begin("Another Window", &hud->show_example_window); - ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); - ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); - ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); - ImGui::End(); - } -} diff --git a/examples/ios_example/imguiex/debug_hud.h b/examples/ios_example/imguiex/debug_hud.h deleted file mode 100644 index 17122f5..0000000 --- a/examples/ios_example/imguiex/debug_hud.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// debug_hud.h -// imguiex - -#pragma once - -typedef struct DebugHUD -{ - bool show_test_window; - bool show_example_window; - float rotation_speed; - float cubeColor1[4]; - float cubeColor2[4]; -} DebugHUD; - -#if __cplusplus -extern "C" { -#endif - -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); - -#if __cplusplus -} -#endif diff --git a/examples/ios_example/imguiex/imgui_ex_icon.png b/examples/ios_example/imguiex/imgui_ex_icon.png deleted file mode 100644 index 820e4d7..0000000 --- a/examples/ios_example/imguiex/imgui_ex_icon.png +++ /dev/null Binary files differ diff --git a/examples/ios_example/imguiex/imgui_impl_ios.h b/examples/ios_example/imguiex/imgui_impl_ios.h deleted file mode 100644 index 9b01dd3..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.h +++ /dev/null @@ -1,22 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -// by Joel Davis (joeld42@gmail.com) - -#pragma once - -#include -#include - -@interface ImGuiHelper : NSObject - -- (id) initWithView: (UIView *)view; - -- (void)connectServer: (NSString*)serverName; - -- (void)render; -- (void)newFrame; - -@end diff --git a/examples/ios_example/imguiex/imgui_impl_ios.mm b/examples/ios_example/imguiex/imgui_impl_ios.mm deleted file mode 100644 index b286c4d..0000000 --- a/examples/ios_example/imguiex/imgui_impl_ios.mm +++ /dev/null @@ -1,803 +0,0 @@ -// ImGui iOS+OpenGL+Synergy binding -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. -// Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. - -#import -#import - -#include -#include -#include -#include - -#include "imgui_impl_ios.h" -#include "imgui.h" - -#include "uSynergy.h" - -// From Carbon HIToolbox/Events.h -// FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 -enum { - kVK_ANSI_A = 0x00, - kVK_ANSI_S = 0x01, - kVK_ANSI_D = 0x02, - kVK_ANSI_F = 0x03, - kVK_ANSI_H = 0x04, - kVK_ANSI_G = 0x05, - kVK_ANSI_Z = 0x06, - kVK_ANSI_X = 0x07, - kVK_ANSI_C = 0x08, - kVK_ANSI_V = 0x09, - kVK_ANSI_B = 0x0B, - kVK_ANSI_Q = 0x0C, - kVK_ANSI_W = 0x0D, - kVK_ANSI_E = 0x0E, - kVK_ANSI_R = 0x0F, - kVK_ANSI_Y = 0x10, - kVK_ANSI_T = 0x11, - kVK_ANSI_1 = 0x12, - kVK_ANSI_2 = 0x13, - kVK_ANSI_3 = 0x14, - kVK_ANSI_4 = 0x15, - kVK_ANSI_6 = 0x16, - kVK_ANSI_5 = 0x17, - kVK_ANSI_Equal = 0x18, - kVK_ANSI_9 = 0x19, - kVK_ANSI_7 = 0x1A, - kVK_ANSI_Minus = 0x1B, - kVK_ANSI_8 = 0x1C, - kVK_ANSI_0 = 0x1D, - kVK_ANSI_RightBracket = 0x1E, - kVK_ANSI_O = 0x1F, - kVK_ANSI_U = 0x20, - kVK_ANSI_LeftBracket = 0x21, - kVK_ANSI_I = 0x22, - kVK_ANSI_P = 0x23, - kVK_ANSI_L = 0x25, - kVK_ANSI_J = 0x26, - kVK_ANSI_Quote = 0x27, - kVK_ANSI_K = 0x28, - kVK_ANSI_Semicolon = 0x29, - kVK_ANSI_Backslash = 0x2A, - kVK_ANSI_Comma = 0x2B, - kVK_ANSI_Slash = 0x2C, - kVK_ANSI_N = 0x2D, - kVK_ANSI_M = 0x2E, - kVK_ANSI_Period = 0x2F, - kVK_ANSI_Grave = 0x32, - kVK_ANSI_KeypadDecimal = 0x41, - kVK_ANSI_KeypadMultiply = 0x43, - kVK_ANSI_KeypadPlus = 0x45, - kVK_ANSI_KeypadClear = 0x47, - kVK_ANSI_KeypadDivide = 0x4B, - kVK_ANSI_KeypadEnter = 0x4C, - kVK_ANSI_KeypadMinus = 0x4E, - kVK_ANSI_KeypadEquals = 0x51, - kVK_ANSI_Keypad0 = 0x52, - kVK_ANSI_Keypad1 = 0x53, - kVK_ANSI_Keypad2 = 0x54, - kVK_ANSI_Keypad3 = 0x55, - kVK_ANSI_Keypad4 = 0x56, - kVK_ANSI_Keypad5 = 0x57, - kVK_ANSI_Keypad6 = 0x58, - kVK_ANSI_Keypad7 = 0x59, - kVK_ANSI_Keypad8 = 0x5B, - kVK_ANSI_Keypad9 = 0x5C -}; - -/* keycodes for keys that are independent of keyboard layout*/ -enum { - kVK_Return = 0x24, - kVK_Tab = 0x30, - kVK_Space = 0x31, - kVK_Delete = 0x33, - kVK_Escape = 0x35, - kVK_Command = 0x37, - kVK_Shift = 0x38, - kVK_CapsLock = 0x39, - kVK_Option = 0x3A, - kVK_Control = 0x3B, - kVK_RightShift = 0x3C, - kVK_RightOption = 0x3D, - kVK_RightControl = 0x3E, - kVK_Function = 0x3F, - kVK_F17 = 0x40, - kVK_VolumeUp = 0x48, - kVK_VolumeDown = 0x49, - kVK_Mute = 0x4A, - kVK_F18 = 0x4F, - kVK_F19 = 0x50, - kVK_F20 = 0x5A, - kVK_F5 = 0x60, - kVK_F6 = 0x61, - kVK_F7 = 0x62, - kVK_F3 = 0x63, - kVK_F8 = 0x64, - kVK_F9 = 0x65, - kVK_F11 = 0x67, - kVK_F13 = 0x69, - kVK_F16 = 0x6A, - kVK_F14 = 0x6B, - kVK_F10 = 0x6D, - kVK_F12 = 0x6F, - kVK_F15 = 0x71, - kVK_Help = 0x72, - kVK_Home = 0x73, - kVK_PageUp = 0x74, - kVK_ForwardDelete = 0x75, - kVK_F4 = 0x76, - kVK_End = 0x77, - kVK_F2 = 0x78, - kVK_PageDown = 0x79, - kVK_F1 = 0x7A, - kVK_LeftArrow = 0x7B, - kVK_RightArrow = 0x7C, - kVK_DownArrow = 0x7D, - kVK_UpArrow = 0x7E -}; - -static char g_keycodeCharUnshifted[256] = {}; -static char g_keycodeCharShifted[256] = {}; - -//static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static float g_mouseWheelX = 0.0f; -static float g_mouseWheelY = 0.0f; - -static GLuint g_FontTexture = 0; -static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; -static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; -static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static size_t g_VboSize = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0; -static float g_displayScale; - -static int usynergy_sockfd; -static bool g_synergyPtrActive = false; -static uint16_t g_mousePosX = 0; -static uint16_t g_mousePosY = 0; - -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); -bool ImGui_ImplIOS_CreateDeviceObjects(); - -static NSString *g_serverName; - -uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) -{ - // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since - // uSynergy does not support SSL. - - NSLog( @"Connect Func!"); - struct addrinfo hints, *res; - - // first, load up address structs with getaddrinfo(): - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever - hints.ai_socktype = SOCK_STREAM; - - // get server address - getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); - - if (!res) - { - NSLog( @"Could not find server: %@", g_serverName ); - return USYNERGY_FALSE; - } - - // make a socket: - usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - - // connect it to the address and port we passed in to getaddrinfo(): - int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); - if (!ret) { - NSLog( @"Connect suceeded..."); - } else { - NSLog( @"Connect failed, %d", ret ); - } - - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) -{ -// NSLog( @"Send Func" ); - send( usynergy_sockfd, buffer, length, 0 ); - - return USYNERGY_TRUE; -} - -uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) -{ - *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); - - return USYNERGY_TRUE; -} - -void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) -{ - usleep( timeMs * 1000 ); -} - -uint32_t ImGui_GetTimeFunc() -{ - struct timeval tv; - gettimeofday(&tv, NULL); - - return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); -} - -void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) -{ - puts(text); -} - -void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) -{ - g_synergyPtrActive = active; -// printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); -} - -void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, - uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) -{ -// printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y, wheelX, wheelY ); - uSynergyContext *ctx = (uSynergyContext*)cookie; - g_mousePosX = x; - g_mousePosY = y; - g_mouseWheelX = wheelX; - g_mouseWheelY = wheelY; - g_MousePressed[0] = buttonLeft; - g_MousePressed[1] = buttonMiddle; - g_MousePressed[2] = buttonRight; - - ctx->m_mouseWheelX = 0; - ctx->m_mouseWheelY = 0; -} - -void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, - uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) -{ - int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); - ImGuiIO& io = ImGui::GetIO(); - io.KeysDown[key] = down; - io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); - io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); - io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); - io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); - - // Add this as keyboard input - if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL)) - { - // If this key maps to a character input, apply it - int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; - io.AddInputCharacter((unsigned short)charForKeycode); - } - -} - -void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) -{ - printf("Synergy: joystick callback TODO\n"); -} - -void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) -{ - printf("Synergy: clipboard callback TODO\n" ); -} - - -@interface ImGuiHelper () -{ - BOOL _mouseDown; - BOOL _mouseTapped; - CGPoint _touchPos; - - uSynergyContext _synergyCtx; - dispatch_queue_t _synergyQueue; -} -@property (nonatomic, weak) UIView *view; -@property (nonatomic, strong) NSString *serverName; - -@end - -@implementation ImGuiHelper - -- (id) initWithView: (UIView *)view -{ - self = [super init]; - if (self) - { - self.view = view; - - [self setupImGuiHooks]; - } - return self; -} - -- (void)setupKeymaps -{ - // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, - // but this was the best I could come up with. There are some device independent API's available - // to convert scan codes to unicode characters, but these are only available on mac and not - // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do - // this or any way to get the character codes out of usynergy. - g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; - g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; - g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; - g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; - g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; - g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; - g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; - g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; - g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; - g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; - g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; - g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; - g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; - g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; - g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; - g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; - g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; - g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; - g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; - g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; - g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; - g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; - g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; - g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; - g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; - g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; - g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; - g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; - g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; - g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; - g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; - g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; - g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; - g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharUnshifted[ kVK_Space ]=' '; - - g_keycodeCharShifted[ kVK_ANSI_A ]='A'; - g_keycodeCharShifted[ kVK_ANSI_S ]='S'; - g_keycodeCharShifted[ kVK_ANSI_D ]='D'; - g_keycodeCharShifted[ kVK_ANSI_F ]='F'; - g_keycodeCharShifted[ kVK_ANSI_H ]='H'; - g_keycodeCharShifted[ kVK_ANSI_G ]='G'; - g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; - g_keycodeCharShifted[ kVK_ANSI_X ]='X'; - g_keycodeCharShifted[ kVK_ANSI_C ]='C'; - g_keycodeCharShifted[ kVK_ANSI_V ]='V'; - g_keycodeCharShifted[ kVK_ANSI_B ]='B'; - g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; - g_keycodeCharShifted[ kVK_ANSI_W ]='W'; - g_keycodeCharShifted[ kVK_ANSI_E ]='E'; - g_keycodeCharShifted[ kVK_ANSI_R ]='R'; - g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; - g_keycodeCharShifted[ kVK_ANSI_T ]='T'; - g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; - g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; - g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; - g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; - g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; - g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; - g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; - g_keycodeCharShifted[ kVK_ANSI_9 ]='('; - g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; - g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; - g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; - g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; - g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; - g_keycodeCharShifted[ kVK_ANSI_O ]='O'; - g_keycodeCharShifted[ kVK_ANSI_U ]='U'; - g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; - g_keycodeCharShifted[ kVK_ANSI_I ]='I'; - g_keycodeCharShifted[ kVK_ANSI_P ]='P'; - g_keycodeCharShifted[ kVK_ANSI_L ]='L'; - g_keycodeCharShifted[ kVK_ANSI_J ]='J'; - g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; - g_keycodeCharShifted[ kVK_ANSI_K ]='K'; - g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; - g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; - g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; - g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; - g_keycodeCharShifted[ kVK_ANSI_N ]='N'; - g_keycodeCharShifted[ kVK_ANSI_M ]='M'; - g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; - g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; - g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; - g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; - g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; - g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; - g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; - g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; - g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; - g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; - g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; - g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; - g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; - g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; - g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; - g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; - g_keycodeCharShifted[ kVK_Space ]=' '; -} - -- (void)setupImGuiHooks -{ - ImGuiIO &io = ImGui::GetIO(); - - [self setupKeymaps]; - - // Account for retina display for glScissor - g_displayScale = [[UIScreen mainScreen] scale]; - - ImGuiStyle &style = ImGui::GetStyle(); - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - - io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; - - UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; - [self.view addGestureRecognizer:panRecognizer]; - - UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; - [self.view addGestureRecognizer:tapRecoginzer]; - - // Fill out the Synergy key map - // (for some reason synergy scan codes are off by 1) - io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; - io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; - io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; - io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; - io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; - io.KeyMap[ImGuiKey_Home] = kVK_Home+1; - io.KeyMap[ImGuiKey_End] = kVK_End+1; - io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; - io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; - io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; - io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; - io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; - io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; - io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; - io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; - io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; - io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; -} - -- (void)connectServer: (NSString*)serverName -{ - self.serverName = serverName; - g_serverName = serverName; - - // Init synergy - NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; - - uSynergyInit( &_synergyCtx ); - _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); - _synergyCtx.m_clientWidth = self.view.bounds.size.width; - _synergyCtx.m_clientHeight = self.view.bounds.size.height; - - _synergyCtx.m_connectFunc = ImGui_ConnectFunc; - _synergyCtx.m_sendFunc = ImGui_SendFunc; - _synergyCtx.m_receiveFunc = ImGui_RecvFunc; - _synergyCtx.m_sleepFunc = ImGui_SleepFunc; - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; - - _synergyCtx.m_traceFunc = ImGui_TraceFunc; - _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; - _synergyCtx.m_mouseCallback = ImGui_MouseCallback; - _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; - - _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; - - // Create a background thread for synergy - _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); - dispatch_async( _synergyQueue, ^{ - while (1) { - uSynergyUpdate( &_synergyCtx ); - } - }); -} - - -- (void)viewDidPan: (UIPanGestureRecognizer *)recognizer -{ - - if ((recognizer.state == UIGestureRecognizerStateBegan) || - (recognizer.state == UIGestureRecognizerStateChanged)) - { - _mouseDown = YES; - _touchPos = [recognizer locationInView:self.view]; - } - else - { - _mouseDown = NO; - _touchPos = CGPointMake( -1, -1 ); - } -} - -- (void)viewDidTap: (UITapGestureRecognizer*)recognizer -{ - _touchPos = [recognizer locationInView:self.view]; - _mouseTapped = YES; -} - -- (void)render -{ - ImGui::Render(); -} - -- (void)newFrame -{ - ImGuiIO& io = ImGui::GetIO(); - ImGuiStyle &style = ImGui::GetStyle(); - - if (!g_FontTexture) - { - ImGui_ImplIOS_CreateDeviceObjects(); - } - - io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); - - io.MouseDrawCursor = g_synergyPtrActive; - if (g_synergyPtrActive) - { - style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); - io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); - for (int i=0; i < 3; i++) - { - io.MouseDown[i] = g_MousePressed[i]; - } - - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in - io.MouseWheel = g_mouseWheelY / 500.0; - } - else - { - // Synergy not active, use touch events - style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); - io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); - if ((_mouseDown) || (_mouseTapped)) - { - io.MouseDown[0] = true; - _mouseTapped = NO; - } - else - { - io.MouseDown[0] = false; - } - } - - ImGui::NewFrame(); -} -@end - -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -// If text or lines are blurry when integrating ImGui in your engine: -// - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) -// NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES -static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled - GLint last_program, last_texture; - glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - // Setup orthographic projection matrix - const float width = ImGui::GetIO().DisplaySize.x; - const float height = ImGui::GetIO().DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/width, 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/-height, 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { -1.0f, 1.0f, 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); - - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - ImDrawList* cmd_list = draw_data->CmdLists[n]; - ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); - - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - int needed_vtx_size = cmd_list->VtxBuffer.size() * sizeof(ImDrawVert); - if (g_VboSize < needed_vtx_size) - { - // Grow our buffer if needed - g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); - } - - unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); - if (!vtx_data) - continue; - memcpy(vtx_data, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); - glUnmapBuffer(GL_ARRAY_BUFFER); - - for (const ImDrawCmd* pcmd = cmd_list->CmdBuffer.begin(); pcmd != cmd_list->CmdBuffer.end(); pcmd++) - { - if (pcmd->UserCallback) - { - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); - glScissor((int)(pcmd->ClipRect.x * g_displayScale), - (int)((height - pcmd->ClipRect.w) * g_displayScale), - (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), - (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); - glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); - } - idx_buffer += pcmd->ElemCount; - } - } - - // Restore modified state - glBindVertexArray(0); - glBindBuffer( GL_ARRAY_BUFFER, 0); - glEnable(GL_CULL_FACE); - glEnable(GL_DEPTH_TEST); - glUseProgram(last_program); - glDisable(GL_SCISSOR_TEST); - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -void ImGui_ImplIOS_CreateFontsTexture() -{ - // Build texture atlas - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. - - // Upload texture to graphics system - GLint last_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); - glGenTextures(1, &g_FontTexture); - glBindTexture(GL_TEXTURE_2D, g_FontTexture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; - - // Restore state - glBindTexture(GL_TEXTURE_2D, last_texture); -} - -bool ImGui_ImplIOS_CreateDeviceObjects() -{ - const GLchar *vertex_shader = - "uniform mat4 ProjMtx;\n" - "attribute highp vec2 Position;\n" - "attribute highp vec2 UV;\n" - "attribute highp vec4 Color;\n" - "varying vec2 Frag_UV;\n" - "varying vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " Frag_UV = UV;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" - "}\n"; - - const GLchar* fragment_shader = - "uniform sampler2D Texture;\n" - "varying highp vec2 Frag_UV;\n" - "varying highp vec4 Frag_Color;\n" - "void main()\n" - "{\n" - " gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" - "}\n"; - - g_ShaderHandle = glCreateProgram(); - g_VertHandle = glCreateShader(GL_VERTEX_SHADER); - g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); - glCompileShader(g_VertHandle); - -#if defined(DEBUG) - GLint logLength; - glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); - NSLog(@"VERTEX Shader compile log:\n%s", log); - free(log); - } -#endif - - glCompileShader(g_FragHandle); - -#if defined(DEBUG) - glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); - if (logLength > 0) { - GLchar *log = (GLchar *)malloc(logLength); - glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); - NSLog(@"FRAGMENT Shader compile log:\n%s", log); - free(log); - } -#endif - - glAttachShader(g_ShaderHandle, g_VertHandle); - glAttachShader(g_ShaderHandle, g_FragHandle); - glLinkProgram(g_ShaderHandle); - - g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); - g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); - g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); - g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); - g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); - - glGenBuffers(1, &g_VboHandle); - - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF - glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - ImGui_ImplIOS_CreateFontsTexture(); - - return true; -} diff --git a/examples/ios_example/imguiex/main.m b/examples/ios_example/imguiex/main.m deleted file mode 100644 index faba099..0000000 --- a/examples/ios_example/imguiex/main.m +++ /dev/null @@ -1,13 +0,0 @@ -// -// main.m -// imguiex -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/examples/libs/glfw/include/GLFW/glfw3.h b/examples/libs/glfw/include/GLFW/glfw3.h index 8941449..f8ca3d6 100644 --- a/examples/libs/glfw/include/GLFW/glfw3.h +++ b/examples/libs/glfw/include/GLFW/glfw3.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,58 +38,60 @@ * Doxygen documentation *************************************************************************/ -/*! @defgroup context Context handling +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. * - * This is the reference documentation for context related functions. For more - * information, see the @ref context. + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. */ -/*! @defgroup init Initialization, version and errors +/*! @defgroup context Context reference + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference * * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more information, - * see the @ref intro. + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. */ -/*! @defgroup input Input handling +/*! @defgroup input Input reference * * This is the reference documentation for input related functions and types. - * For more information, see the @ref input. + * For more task-oriented information, see the @ref input_guide. */ -/*! @defgroup monitor Monitor handling +/*! @defgroup monitor Monitor reference * * This is the reference documentation for monitor related functions and types. - * For more information, see the @ref monitor. + * For more task-oriented information, see the @ref monitor_guide. */ -/*! @defgroup window Window handling +/*! @defgroup window Window reference * * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more information, see - * the @ref window. + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. */ /************************************************************************* - * Global definitions + * Compiler- and platform-specific preprocessor work *************************************************************************/ -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -/* Please report any problems that you find with your compiler, which may - * be solved in this section! There are several compilers that I have not - * been able to test this file with yet. - * - * First: If we are we on Windows, we want a single define for it (_WIN32) - * (Note: For Cygwin the compiler flag -mwin32 should be used, but to - * make sure that things run smoothly for Cygwin users, we add __CYGWIN__ - * to the list of "valid Win32 identifiers", which removes the need for - * -mwin32) +/* If we are we on Windows, we want a single define for it. */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)) +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) #define _WIN32 #endif /* _WIN32 */ -/* In order for extension support to be portable, we need to define an - * OpenGL function call method. We use the keyword APIENTRY, which is - * defined for Win32. (Note: Windows also needs this for ) +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. */ #ifndef APIENTRY #ifdef _WIN32 @@ -99,51 +101,30 @@ #endif #endif /* APIENTRY */ -/* The following three defines are here solely to make some Windows-based - * files happy. Theoretically we could include , but - * it has the major drawback of severely polluting our namespace. +/* Some Windows OpenGL headers need this. */ - -/* Under Windows, we need WINGDIAPI defined */ #if !defined(WINGDIAPI) && defined(_WIN32) - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__) - /* Microsoft Visual C++, Borland C++ Builder and Pelles C */ - #define WINGDIAPI __declspec(dllimport) - #elif defined(__LCC__) - /* LCC-Win32 */ - #define WINGDIAPI __stdcall - #else - /* Others (e.g. MinGW, Cygwin) */ - #define WINGDIAPI extern - #endif + #define WINGDIAPI __declspec(dllimport) #define GLFW_WINGDIAPI_DEFINED #endif /* WINGDIAPI */ -/* Some files also need CALLBACK defined */ +/* Some Windows GLU headers need this. + */ #if !defined(CALLBACK) && defined(_WIN32) - #if defined(_MSC_VER) - /* Microsoft Visual C++ */ - #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS) - #define CALLBACK __stdcall - #else - #define CALLBACK - #endif - #else - /* Other Windows compilers */ - #define CALLBACK __stdcall - #endif + #define CALLBACK __stdcall #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Most GL/glu.h variants on Windows need wchar_t - * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */ -#if !defined(GLFW_INCLUDE_NONE) - #include -#endif +/* Most Windows GLU headers need wchar_t. + * The OS X OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include +#include /* Include the chosen client API headers. */ -#if defined(__APPLE_CC__) +#if defined(__APPLE__) #if defined(GLFW_INCLUDE_GLCOREARB) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -174,13 +155,15 @@ #elif defined(GLFW_INCLUDE_ES3) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif #elif defined(GLFW_INCLUDE_ES31) #include #if defined(GLFW_INCLUDE_GLEXT) - #include + #include #endif + #elif defined(GLFW_INCLUDE_VULKAN) + #include #elif !defined(GLFW_INCLUDE_NONE) #include #if defined(GLFW_INCLUDE_GLEXT) @@ -208,11 +191,7 @@ #define GLFWAPI __declspec(dllexport) #elif defined(_WIN32) && defined(GLFW_DLL) /* We are calling GLFW as a Win32 DLL */ - #if defined(__LCC__) - #define GLFWAPI extern - #else - #define GLFWAPI __declspec(dllimport) - #endif + #define GLFWAPI __declspec(dllimport) #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) /* We are building GLFW as a shared / dynamic library */ #define GLFWAPI __attribute__((visibility("default"))) @@ -221,8 +200,6 @@ #define GLFWAPI #endif -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - /************************************************************************* * GLFW API tokens @@ -242,7 +219,7 @@ * backward-compatible. * @ingroup init */ -#define GLFW_VERSION_MINOR 1 +#define GLFW_VERSION_MINOR 2 /*! @brief The revision number of the GLFW library. * * This is incremented when a bug fix release is made that does not contain any @@ -252,6 +229,24 @@ #define GLFW_VERSION_REVISION 0 /*! @} */ +/*! @name Boolean values + * @{ */ +/*! @brief One. + * + * One. Seriously. You don't _need_ to use this symbol in your code. It's + * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * or `GL_TRUE` or whatever you want. + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * Zero. Seriously. You don't _need_ to use this symbol in your code. It's + * just just semantic sugar for the number 0. You can use `0` or `false` or + * `_False` or `GL_FALSE` or whatever you want. + */ +#define GLFW_FALSE 0 +/*! @} */ + /*! @name Key and button actions * @{ */ /*! @brief The key or mouse button was released. @@ -426,6 +421,7 @@ #define GLFW_KEY_RIGHT_ALT 346 #define GLFW_KEY_RIGHT_SUPER 347 #define GLFW_KEY_MENU 348 + #define GLFW_KEY_LAST GLFW_KEY_MENU /*! @} */ @@ -505,12 +501,11 @@ * @{ */ /*! @brief GLFW has not been initialized. * - * This occurs if a GLFW function was called that may not be called unless the + * This occurs if a GLFW function was called that must not be called unless the * library is [initialized](@ref intro_init). * - * @par Analysis - * Application programmer error. Initialize GLFW before calling any function - * that requires initialization. + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. */ #define GLFW_NOT_INITIALIZED 0x00010001 /*! @brief No context is current for this thread. @@ -519,9 +514,8 @@ * current OpenGL or OpenGL ES context but no context is current on the calling * thread. One such function is @ref glfwSwapInterval. * - * @par Analysis - * Application programmer error. Ensure a context is current before calling - * functions that require a current context. + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. */ #define GLFW_NO_CURRENT_CONTEXT 0x00010002 /*! @brief One of the arguments to the function was an invalid enum value. @@ -530,8 +524,7 @@ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref * glfwGetWindowAttrib. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_ENUM 0x00010003 /*! @brief One of the arguments to the function was an invalid value. @@ -542,46 +535,41 @@ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead * result in a @ref GLFW_VERSION_UNAVAILABLE error. * - * @par Analysis - * Application programmer error. Fix the offending call. + * @analysis Application programmer error. Fix the offending call. */ #define GLFW_INVALID_VALUE 0x00010004 /*! @brief A memory allocation failed. * * A memory allocation failed. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested client API on the - * system. +/*! @brief GLFW could not find support for the requested API on the system. * - * GLFW could not find support for the requested client API on the system. + * GLFW could not find support for the requested API on the system. * - * @par Analysis - * The installed graphics driver does not support the requested client API, or - * does not support it via the chosen context creation backend. Below are - * a few examples. + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. * * @par * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. + * driver. Older graphics drivers do not support Vulkan. */ #define GLFW_API_UNAVAILABLE 0x00010006 /*! @brief The requested OpenGL or OpenGL ES version is not available. * - * The requested OpenGL or OpenGL ES version (including any requested profile - * or context option) is not available on this machine. + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. * - * @par Analysis - * The machine does not support your requirements. If your application is - * sufficiently flexible, downgrade your requirements and try again. - * Otherwise, inform the user that their machine does not match your + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your * requirements. * * @par @@ -597,9 +585,9 @@ * A platform-specific error occurred that does not match any of the more * specific categories. * - * @par Analysis - * A bug in GLFW or the underlying operating system. Report the bug to our - * [issue tracker](https://github.com/glfw/glfw/issues). + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). */ #define GLFW_PLATFORM_ERROR 0x00010008 /*! @brief The requested format is not supported or available. @@ -610,8 +598,7 @@ * If emitted when querying the clipboard, the contents of the clipboard could * not be converted to the requested format. * - * @par Analysis - * If emitted during window creation, one or more + * @analysis If emitted during window creation, one or more * [hard constraints](@ref window_hints_hard) did not match any of the * available pixel formats. If your application is sufficiently flexible, * downgrade your requirements and try again. Otherwise, inform the user that @@ -622,6 +609,14 @@ * the user, as appropriate. */ #define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A /*! @} */ #define GLFW_FOCUSED 0x00020001 @@ -631,6 +626,7 @@ #define GLFW_DECORATED 0x00020005 #define GLFW_AUTO_ICONIFY 0x00020006 #define GLFW_FLOATING 0x00020007 +#define GLFW_MAXIMIZED 0x00020008 #define GLFW_RED_BITS 0x00021001 #define GLFW_GREEN_BITS 0x00021002 @@ -658,7 +654,9 @@ #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +#define GLFW_NO_API 0 #define GLFW_OPENGL_API 0x00030001 #define GLFW_OPENGL_ES_API 0x00030002 @@ -736,14 +734,37 @@ * Generic function pointer used for returning client API function pointers * without forcing a cast from a regular pointer. * + * @sa @ref context_glext + * @sa glfwGetProcAddress + * + * @since Added in version 3.0. + * @ingroup context */ typedef void (*GLFWglproc)(void); +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + /*! @brief Opaque monitor object. * * Opaque monitor object. * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWmonitor GLFWmonitor; @@ -752,6 +773,10 @@ * * Opaque window object. * + * @see @ref window_object + * + * @since Added in version 3.0. + * * @ingroup window */ typedef struct GLFWwindow GLFWwindow; @@ -760,6 +785,10 @@ * * Opaque cursor object. * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * * @ingroup cursor */ typedef struct GLFWcursor GLFWcursor; @@ -771,8 +800,11 @@ * @param[in] error An [error code](@ref errors). * @param[in] description A UTF-8 encoded string describing the error. * + * @sa @ref error_handling * @sa glfwSetErrorCallback * + * @since Added in version 3.0. + * * @ingroup init */ typedef void (* GLFWerrorfun)(int,const char*); @@ -787,8 +819,11 @@ * @param[in] ypos The new y-coordinate, in screen coordinates, of the * upper-left corner of the client area of the window. * + * @sa @ref window_pos * @sa glfwSetWindowPosCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); @@ -801,8 +836,12 @@ * @param[in] width The new width, in screen coordinates, of the window. * @param[in] height The new height, in screen coordinates, of the window. * + * @sa @ref window_size * @sa glfwSetWindowSizeCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); @@ -813,8 +852,12 @@ * * @param[in] window The window that the user attempted to close. * + * @sa @ref window_close * @sa glfwSetWindowCloseCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); @@ -825,8 +868,12 @@ * * @param[in] window The window whose content needs to be refreshed. * + * @sa @ref window_refresh * @sa glfwSetWindowRefreshCallback * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * * @ingroup window */ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); @@ -836,11 +883,14 @@ * This is the function signature for window focus callback functions. * * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GL_TRUE` if the window was given input focus, or - * `GL_FALSE` if it lost it. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. * + * @sa @ref window_focus * @sa glfwSetWindowFocusCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); @@ -851,11 +901,14 @@ * functions. * * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE` - * if it was restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. * + * @sa @ref window_iconify * @sa glfwSetWindowIconifyCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); @@ -869,8 +922,11 @@ * @param[in] width The new width, in pixels, of the framebuffer. * @param[in] height The new height, in pixels, of the framebuffer. * + * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * + * @since Added in version 3.0. + * * @ingroup window */ typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); @@ -886,8 +942,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_mouse_button * @sa glfwSetMouseButtonCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); @@ -897,11 +957,16 @@ * This is the function signature for cursor position callback functions. * * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the client area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * client area. * + * @sa @ref cursor_pos * @sa glfwSetCursorPosCallback * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * * @ingroup input */ typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); @@ -911,11 +976,14 @@ * This is the function signature for cursor enter/leave callback functions. * * @param[in] window The window that received the event. - * @param[in] entered `GL_TRUE` if the cursor entered the window's client - * area, or `GL_FALSE` if it left it. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client + * area, or `GLFW_FALSE` if it left it. * + * @sa @ref cursor_enter * @sa glfwSetCursorEnterCallback * + * @since Added in version 3.0. + * * @ingroup input */ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); @@ -928,8 +996,11 @@ * @param[in] xoffset The scroll offset along the x-axis. * @param[in] yoffset The scroll offset along the y-axis. * + * @sa @ref scrolling * @sa glfwSetScrollCallback * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * * @ingroup input */ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); @@ -945,8 +1016,12 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_key * @sa glfwSetKeyCallback * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * * @ingroup input */ typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); @@ -958,8 +1033,12 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the character. * + * @sa @ref input_char * @sa glfwSetCharCallback * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * * @ingroup input */ typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); @@ -976,8 +1055,11 @@ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were * held down. * + * @sa @ref input_char * @sa glfwSetCharModsCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); @@ -988,10 +1070,13 @@ * * @param[in] window The window that received the event. * @param[in] count The number of dropped files. - * @param[in] names The UTF-8 encoded path names of the dropped files. + * @param[in] paths The UTF-8 encoded file and/or directory path names. * + * @sa @ref path_drop * @sa glfwSetDropCallback * + * @since Added in version 3.1. + * * @ingroup input */ typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**); @@ -1003,16 +1088,42 @@ * @param[in] monitor The monitor that was connected or disconnected. * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. * + * @sa @ref monitor_event * @sa glfwSetMonitorCallback * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); +/*! @brief The function signature for joystick configuration callbacks. + * + * This is the function signature for joystick configuration callback + * functions. + * + * @param[in] joy The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. + * + * @sa @ref joystick_event + * @sa glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + /*! @brief Video mode type. * * This describes a single video mode. * + * @sa @ref monitor_modes + * @sa glfwGetVideoMode glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * * @ingroup monitor */ typedef struct GLFWvidmode @@ -1041,8 +1152,11 @@ * * This describes the gamma ramp for a monitor. * + * @sa @ref monitor_gamma * @sa glfwGetGammaRamp glfwSetGammaRamp * + * @since Added in version 3.0. + * * @ingroup monitor */ typedef struct GLFWgammaramp @@ -1062,6 +1176,11 @@ } GLFWgammaramp; /*! @brief Image data. + * + * @sa @ref cursor_custom + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. */ typedef struct GLFWimage { @@ -1092,29 +1211,24 @@ * succeeds, you should call @ref glfwTerminate before the application exits. * * Additional calls to this function after successful initialization but before - * termination will return `GL_TRUE` immediately. + * termination will return `GLFW_TRUE` immediately. * - * @return `GL_TRUE` if successful, or `GL_FALSE` if an + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an * [error](@ref error_handling) occurred. * - * @remarks __OS X:__ This function will change the current directory of the + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @osx This function will change the current directory of the * application to the `Contents/Resources` subdirectory of the application's * bundle, if present. This can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to - * `"C"` then the environment's locale will be applied to that category. This - * is done because character input will not function when `LC_CTYPE` is set to - * `"C"`. If another locale was set before this function was called, it will - * be left untouched. - * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwTerminate * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1132,21 +1246,21 @@ * call this function, as it is called by @ref glfwInit before it returns * failure. * - * @remarks This function may be called before @ref glfwInit. + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. * - * @warning No window's context may be current on another thread when this - * function is called. + * @remark This function may be called before @ref glfwInit. * - * @par Reentrancy - * This function may not be called from a callback. + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref intro_init * @sa glfwInit * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1158,22 +1272,22 @@ * library. It is intended for when you are using GLFW as a shared library and * want to ensure that you are using the minimum required version. * - * Any or all of the version arguments may be `NULL`. This function always - * succeeds. + * Any or all of the version arguments may be `NULL`. * * @param[out] major Where to store the major version number, or `NULL`. * @param[out] minor Where to store the minor version number, or `NULL`. * @param[out] rev Where to store the revision number, or `NULL`. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may be called from any thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersionString * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup init */ @@ -1184,28 +1298,27 @@ * This function returns the compile-time generated * [version string](@ref intro_version_string) of the GLFW library binary. It * describes the version, platform, compiler and any platform-specific - * compile-time options. + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. * * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function already provides the version of the running - * library binary. + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. * - * This function always succeeds. + * @return The ASCII encoded GLFW version string. * - * @return The GLFW version string. + * @errors None. * - * @remarks This function may be called before @ref glfwInit. + * @remark This function may be called before @ref glfwInit. * - * @par Pointer Lifetime - * The returned string is static and compile-time generated. + * @pointer_lifetime The returned string is static and compile-time generated. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref intro_version * @sa glfwGetVersion * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1231,14 +1344,15 @@ * callback. * @return The previously set callback, or `NULL` if no callback was set. * - * @remarks This function may be called before @ref glfwInit. + * @errors None. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref error_handling * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup init */ @@ -1247,26 +1361,27 @@ /*! @brief Returns the currently connected monitors. * * This function returns an array of handles for all currently connected - * monitors. + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. * * @param[out] count Where to store the number of monitors in the returned * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if an - * [error](@ref error_handling) occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is guaranteed to be valid only until the monitor configuration - * changes or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_monitors * @sa @ref monitor_event * @sa glfwGetPrimaryMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1275,18 +1390,22 @@ /*! @brief Returns the primary monitor. * * This function returns the primary monitor. This is usually the monitor - * where elements like the Windows task bar or the OS X menu bar is located. + * where elements like the task bar or global menu bar are located. * - * @return The primary monitor, or `NULL` if an [error](@ref error_handling) - * occurred. + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. * * @sa @ref monitor_monitors * @sa glfwGetMonitors * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1304,12 +1423,14 @@ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1334,15 +1455,16 @@ * @param[out] heightMM Where to store the height, in millimetres, of the * monitor's display area, or `NULL`. * - * @remarks __Windows:__ The OS calculates the returned physical size from the + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the * current resolution and system DPI instead of querying the monitor EDID data. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1358,17 +1480,17 @@ * @return The UTF-8 encoded name of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_properties * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1385,15 +1507,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @bug __X11:__ This callback is not yet called on monitor configuration - * changes. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_event * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1412,21 +1532,21 @@ * @return An array of video modes, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected, this - * function is called again for that monitor or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoMode * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Changed to return an array of modes for a specific monitor. + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. * * @ingroup monitor */ @@ -1442,18 +1562,19 @@ * @return The current mode of the monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified monitor is disconnected or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_modes * @sa glfwGetVideoModes * - * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`. + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. * * @ingroup monitor */ @@ -1462,17 +1583,20 @@ /*! @brief Generates a gamma ramp and sets it for the specified monitor. * * This function generates a 256-element gamma ramp from the specified exponent - * and then calls @ref glfwSetGammaRamp with it. + * and then calls @ref glfwSetGammaRamp with it. The value must be a finite + * number greater than zero. * * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] gamma The desired exponent. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1486,18 +1610,19 @@ * @return The current gamma ramp, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned structure and its arrays are allocated and freed by GLFW. You - * should not free them yourself. They are valid until the specified monitor - * is disconnected, this function is called again for that monitor or the - * library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1512,17 +1637,22 @@ * @param[in] monitor The monitor whose gamma ramp to set. * @param[in] ramp The gamma ramp to use. * - * @note Gamma ramp sizes other than 256 are not supported by all hardware. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Pointer Lifetime - * The specified gamma ramp is copied before this function returns. + * @remark Gamma ramp sizes other than 256 are not supported by all platforms + * or graphics hardware. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @win32 The gamma ramp size must be 256. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref monitor_gamma * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup monitor */ @@ -1533,13 +1663,14 @@ * This function resets all window hints to their * [default values](@ref window_hints_values). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwWindowHint * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1552,20 +1683,26 @@ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is * terminated. * - * @param[in] target The [window hint](@ref window_hints) to set. - * @param[in] hint The new value of the window hint. + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. * - * @par Thread Safety - * This function may only be called from the main thread. + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hints * @sa glfwDefaultWindowHints * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`. + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. * * @ingroup window */ -GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI void glfwWindowHint(int hint, int value); /*! @brief Creates a window and its associated context. * @@ -1582,21 +1719,21 @@ * requested, as not all parameters and hints are * [hard constraints](@ref window_hints_hard). This includes the size of the * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, use queries like @ref - * glfwGetWindowAttrib and @ref glfwGetWindowSize. + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. * * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, windowed mode will be used. Unless - * you have a way for the user to choose a specific monitor, it is recommended - * that you pick the primary monitor. For more information on how to query - * connected monitors, see @ref monitor_monitors. + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. * * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window has input - * focus, the supported video mode most closely matching the desired video mode - * is set for the specified monitor. For more information about full screen - * windows, including the creation of so called _windowed full screen_ or - * _borderless full screen_ windows, see @ref window_windowed_full_screen. + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. * * By default, newly created windows use the placement recommended by the * window system. To create the window at a specific position, make it @@ -1604,8 +1741,8 @@ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) * it. * - * If a full screen window has input focus, the screensaver is prohibited from - * starting. + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. * * Window systems put limits on window sizes. Very large or very small window * dimensions may be overridden by the window system on creation. Check the @@ -1619,50 +1756,67 @@ * @param[in] height The desired height, in screen coordinates, of the window. * This must be greater than zero. * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for * windowed mode. * @param[in] share The window whose context to share resources with, or `NULL` * to not share resources. * @return The handle of the created window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @remarks __Windows:__ Window creation will fail if the Microsoft GDI - * software OpenGL implementation is the only one available. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. * - * @remarks __Windows:__ If the executable has an icon resource named - * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is - * present, the `IDI_WINLOGO` icon will be used instead. + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. * - * @remarks __Windows:__ The context to share resources with may not be current - * on any other thread. + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` + * it will be set as the icon for the window. If no such icon is present, the + * `IDI_WINLOGO` icon will be used instead. * - * @remarks __OS X:__ The GLFW window has no icon, as it is not a document + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @osx The GLFW window has no icon, as it is not a document * window, but the dock icon will be the same as the application bundle's icon. * For more information on bundles, see the * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remarks __OS X:__ The first time a window is created the menu bar is - * populated with common commands like Hide, Quit and About. The About entry - * opens a minimal about dialog with information from the application's bundle. - * The menu bar can be disabled with a + * @remark @osx The first time a window is created the menu bar is populated + * with common commands like Hide, Quit and About. The About entry opens + * a minimal about dialog with information from the application's bundle. The + * menu bar can be disabled with a * [compile-time option](@ref compile_options_osx). * - * @remarks __X11:__ There is no mechanism for setting the window icon yet. + * @remark @osx On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the `NSHighResolutionCapable` + * key is enabled in the application bundle's `Info.plist`. For more + * information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. * - * @remarks __X11:__ Some window managers will not respect the placement of + * @remark @x11 There is no mechanism for setting the window icon yet. + * + * @remark @x11 Some window managers will not respect the placement of * initially hidden windows. * - * @par Reentrancy - * This function may not be called from a callback. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwDestroyWindow * - * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`. + * @since Added in version 3.0. Replaces `glfwOpenWindow`. * * @ingroup window */ @@ -1678,19 +1832,20 @@ * * @param[in] window The window to destroy. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * * @note The context of the specified window must not be current on any other * thread when this function is called. * - * @par Reentrancy - * This function may not be called from a callback. + * @reentrancy This function must not be called from a callback. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_creation * @sa glfwCreateWindow * - * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`. + * @since Added in version 3.0. Replaces `glfwCloseWindow`. * * @ingroup window */ @@ -1703,12 +1858,14 @@ * @param[in] window The window to query. * @return The value of the close flag. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1723,12 +1880,14 @@ * @param[in] window The window whose flag to change. * @param[in] value The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_close * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1742,20 +1901,62 @@ * @param[in] window The window whose title to change. * @param[in] title The UTF-8 encoded window title. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @osx The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_title * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @osx The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + /*! @brief Retrieves the position of the client area of the specified window. * * This function retrieves the position, in screen coordinates, of the @@ -1770,13 +1971,15 @@ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of * the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwSetWindowPos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1798,16 +2001,16 @@ * @param[in] xpos The x-coordinate of the upper-left corner of the client area. * @param[in] ypos The y-coordinate of the upper-left corner of the client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * @sa glfwGetWindowPos * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1828,48 +2031,131 @@ * @param[out] height Where to store the height, in screen coordinates, of the * client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwSetWindowSize * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the client area of the specified + * window. If the window is full screen, the size limits only take effect if + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the client + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * client area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the client area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + /*! @brief Sets the size of the client area of the specified window. * * This function sets the size, in screen coordinates, of the client area of * the specified window. * - * For full screen windows, this function selects and switches to the resolution - * closest to the specified size, without affecting the window's context. As - * the context is unaffected, the bit depths of the framebuffer remain - * unchanged. + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. * * The window manager may put limits on what sizes are allowed. GLFW cannot * and should not override these limits. * * @param[in] window The window to resize. - * @param[in] width The desired width of the specified window. - * @param[in] height The desired height of the specified window. + * @param[in] width The desired width, in screen coordinates, of the window + * client area. + * @param[in] height The desired height, in screen coordinates, of the window + * client area. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * @sa glfwGetWindowSize + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1890,13 +2176,15 @@ * @param[out] height Where to store the height, in pixels, of the framebuffer, * or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * @sa glfwSetFramebufferSizeCallback * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -1926,12 +2214,14 @@ * @param[out] bottom Where to store the size, in screen coordinates, of the * bottom edge of the window frame, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -1948,16 +2238,17 @@ * * @param[in] window The window to iconify. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * @sa glfwRestoreWindow + * @sa glfwMaximizeWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -1966,27 +2257,51 @@ /*! @brief Restores the specified window. * * This function restores the specified window if it was previously iconified - * (minimized). If the window is already restored, this function does nothing. + * (minimized) or maximized. If the window is already restored, this function + * does nothing. * * If the specified window is a full screen window, the resolution chosen for * the window is restored on the selected monitor. * * @param[in] window The window to restore. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa glfwIconifyWindow + * @sa glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * * @par Thread Safety * This function may only be called from the main thread. * * @sa @ref window_iconify * @sa glfwIconifyWindow + * @sa glfwRestoreWindow * - * @since Added in GLFW 2.1. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in GLFW 3.2. * * @ingroup window */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); /*! @brief Makes the specified window visible. * @@ -1996,13 +2311,15 @@ * * @param[in] window The window to make visible. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwHideWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2016,18 +2333,48 @@ * * @param[in] window The window to hide. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide * @sa glfwShowWindow * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI void glfwHideWindow(GLFWwindow* window); +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable + * this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is @@ -2037,17 +2384,67 @@ * @return The monitor, or `NULL` if the window is in windowed mode or an error * occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_monitor + * @sa glfwSetWindowMonitor * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window client area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc.. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * client area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * client area. + * @param[in] width The desired with, in screen coordinates, of the client area + * or video mode. + * @param[in] height The desired height, in screen coordinates, of the client + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa glfwGetWindowMonitor + * @sa glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + /*! @brief Returns an attribute of the specified window. * * This function returns the value of an attribute of the specified window or @@ -2059,12 +2456,22 @@ * @return The value of the attribute, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_attribs * - * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and * `glfwGetGLVersion`. * * @ingroup window @@ -2080,13 +2487,15 @@ * @param[in] window The window whose pointer to set. * @param[in] pointer The new value. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwGetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2099,13 +2508,15 @@ * * @param[in] window The window whose pointer to return. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * * @sa @ref window_userptr * @sa glfwSetWindowUserPointer * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2123,12 +2534,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_pos * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2146,15 +2558,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_size * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2177,18 +2588,17 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @remarks __OS X:__ Selecting Quit from the application menu will - * trigger the close callback for all windows. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @osx Selecting Quit from the application menu will trigger the close + * callback for all windows. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_close * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2210,15 +2620,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_refresh * - * @since Added in GLFW 2.5. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. * * @ingroup window */ @@ -2240,12 +2649,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_focus * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2262,12 +2672,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_iconify * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2284,12 +2695,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref window_fbsize * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup window */ @@ -2313,16 +2725,18 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwWaitEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup window */ @@ -2356,21 +2770,69 @@ * * Event processing is not required for joystick input to work. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref events * @sa glfwPollEvents + * @sa glfwWaitEventsTimeout * - * @since Added in GLFW 2.5. + * @since Added in version 2.5. * * @ingroup window */ GLFWAPI void glfwWaitEvents(void); +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * On some platforms, certain callbacks may be called outside of a call to one + * of the event processing functions. + * + * If no windows exist, this function returns immediately. For synchronization + * of threads in applications that do not create windows, use your threading + * library of choice. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa glfwPollEvents + * @sa glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + /*! @brief Posts an empty event to the event queue. * * This function posts an empty event from the current thread to the event @@ -2380,13 +2842,15 @@ * of threads in applications that do not create windows, use your threading * library of choice. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref events * @sa glfwWaitEvents * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup window */ @@ -2402,12 +2866,14 @@ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwSetInputMode * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2428,37 +2894,96 @@ * and unlimited cursor movement. This is useful for implementing for * example 3D camera controls. * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to - * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` * the next time it is called even if the key had been released before the * call. This is useful when you are only interested in whether keys have been * pressed but not when or in which order. * * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If - * sticky mouse buttons are enabled, a mouse button press will ensure that @ref - * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if - * the mouse button had been released before the call. This is useful when you - * are only interested in whether mouse buttons have been pressed but not when - * or in which order. + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. * * @param[in] window The window whose input mode to set. * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or * `GLFW_STICKY_MOUSE_BUTTONS`. * @param[in] value The new value of the specified input mode. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa glfwGetInputMode * - * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`. + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. * * @ingroup input */ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); +/*! @brief Returns the localized name of the specified printable key. + * + * This function returns the localized name of the specified printable key. + * This is intended for displaying key bindings to the user. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise + * the scancode is ignored. If a non-printable key or (if the key is + * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is + * specified, this function returns `NULL`. + * + * This behavior allows you to pass in the arguments passed to the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The localized name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetKeyName, or until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + /*! @brief Returns the last reported state of a keyboard key for the specified * window. * @@ -2478,20 +3003,22 @@ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be * used with this function. * + * __Do not use this function__ to implement [text input](@ref input_char). + * * @param[in] window The desired window. * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is * not a valid key for this function. * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2512,15 +3039,15 @@ * @param[in] button The desired [mouse button](@ref buttons). * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup input */ @@ -2550,13 +3077,15 @@ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to * top edge of the client area, or `NULL`. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwSetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`. + * @since Added in version 3.0. Replaces `glfwGetMousePos`. * * @ingroup input */ @@ -2585,17 +3114,19 @@ * @param[in] ypos The desired y-coordinate, relative to the top edge of the * client area. * - * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it - * may take a moment for the window focus event to arrive. This means you will - * not be able to set the cursor position directly after window creation. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * the window focus event to arrive. This means you may not be able to set the + * cursor position directly after window creation. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * @sa glfwGetCursorPos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`. + * @since Added in version 3.0. Replaces `glfwSetMousePos`. * * @ingroup input */ @@ -2607,9 +3138,9 @@ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. * Any remaining cursors are destroyed by @ref glfwTerminate. * - * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They - * are arranged canonically as packed sequential rows, starting from the - * top-left corner. + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel. They are arranged canonically as packed sequential rows, + * starting from the top-left corner. * * The cursor hotspot is specified in pixels, relative to the upper-left corner * of the cursor image. Like all other coordinate systems in GLFW, the X-axis @@ -2618,24 +3149,24 @@ * @param[in] image The desired cursor image. * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * * @return The handle of the created cursor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The specified image data is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Reentrancy - * This function may not be called from a callback. + * @pointer_lifetime The specified image data is copied before this function + * returns. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwDestroyCursor * @sa glfwCreateStandardCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2647,20 +3178,20 @@ * a window with @ref glfwSetCursor. * * @param[in] shape One of the [standard shapes](@ref shapes). - * * @return A new cursor ready to use or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2674,16 +3205,17 @@ * * @param[in] cursor The cursor object to destroy. * - * @par Reentrancy - * This function may not be called from a callback. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * @sa glfwCreateCursor * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2703,12 +3235,14 @@ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default * arrow cursor. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_object * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2744,15 +3278,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_key * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2783,15 +3316,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 2.4. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2818,12 +3350,13 @@ * @return The previously set callback, or `NULL` if no callback was set or an * error occurred. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_char * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2846,15 +3379,14 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref input_mouse_button * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. Updated callback signature. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. * * @ingroup input */ @@ -2873,12 +3405,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_pos * - * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`. + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. * * @ingroup input */ @@ -2896,12 +3429,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref cursor_enter * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -2922,12 +3456,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref scrolling * - * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`. + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. * * @ingroup input */ @@ -2949,12 +3484,13 @@ * @return The previously set callback, or `NULL` if no callback was set or the * library had not been [initialized](@ref intro_init). * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref path_drop * - * @since Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup input */ @@ -2965,14 +3501,16 @@ * This function returns whether the specified joystick is present. * * @param[in] joy The [joystick](@ref joysticks) to query. - * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`. + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. * * @ingroup input */ @@ -2983,22 +3521,28 @@ * This function returns the values of all axes of the specified joystick. * Each element in the array is a value between -1.0 and 1.0. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of axis values in the returned * array. This is set to zero if an error occurred. * @return An array of axis values, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_axis * - * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`. + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. * * @ingroup input */ @@ -3009,25 +3553,29 @@ * This function returns the state of all buttons of the specified joystick. * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @param[out] count Where to store the number of button states in the returned * array. This is set to zero if an error occurred. * @return An array of button states, or `NULL` if the joystick is not present. * - * @par Pointer Lifetime - * The returned array is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_button * - * @since Added in GLFW 2.2. - * - * @par - * __GLFW 3:__ Changed to return a dynamic array. + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. * * @ingroup input */ @@ -3039,26 +3587,55 @@ * The returned string is allocated and freed by GLFW. You should not free it * yourself. * + * Querying a joystick slot with no device present is not an error, but will + * cause this function to return `NULL`. Call @ref glfwJoystickPresent to + * check device presence. + * * @param[in] joy The [joystick](@ref joysticks) to query. * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick * is not present. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the specified joystick is disconnected, this - * function is called again for that joystick or the library is terminated. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref joystick_name * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ GLFWAPI const char* glfwGetJoystickName(int joy); +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun); + /*! @brief Sets the clipboard to the specified string. * * This function sets the system clipboard to the specified, UTF-8 encoded @@ -3067,16 +3644,18 @@ * @param[in] window The window that will own the clipboard contents. * @param[in] string A UTF-8 encoded string. * - * @par Pointer Lifetime - * The specified string is copied before this function returns. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. * - * @par Thread Safety - * This function may only be called from the main thread. + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwGetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3085,25 +3664,28 @@ /*! @brief Returns the contents of the clipboard as a string. * * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. * * @param[in] window The window that will request the clipboard contents. * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @par Pointer Lifetime - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. It is valid until the next call to @ref + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library * is terminated. * - * @par Thread Safety - * This function may only be called from the main thread. + * @thread_safety This function must only be called from the main thread. * * @sa @ref clipboard * @sa glfwSetClipboardString * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup input */ @@ -3122,12 +3704,14 @@ * @return The current value, in seconds, or zero if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup input */ @@ -3136,21 +3720,71 @@ /*! @brief Sets the GLFW timer. * * This function sets the value of the GLFW timer. It then continues to count - * up from that value. + * up from that value. The value must be a positive finite number less than + * or equal to 18446744073.0, which is approximately 584.5 years. * * @param[in] time The new value, in seconds. * - * @par Thread Safety - * This function may only be called from the main thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of the timer is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Writing of the + * internal timer offset is not atomic. * * @sa @ref time * - * @since Added in GLFW 2.2. + * @since Added in version 2.2. * * @ingroup input */ GLFWAPI void glfwSetTime(double time); +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + /*! @brief Makes the context of the specified window current for the calling * thread. * @@ -3164,16 +3798,22 @@ * whether a context performs this flush by setting the * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint. * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwGetCurrentContext * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3187,13 +3827,14 @@ * @return The window whose context is current, or `NULL` if no window's * context is current. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_current * @sa glfwMakeContextCurrent * - * @since Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup context */ @@ -3201,22 +3842,33 @@ /*! @brief Swaps the front and back buffers of the specified window. * - * This function swaps the front and back buffers of the specified window. If - * the swap interval is greater than zero, the GPU driver waits the specified - * number of screen updates before swapping the buffers. + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. * * @param[in] window The window whose buffers to swap. * - * @par Thread Safety - * This function may be called from any thread. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapInterval * - * @since Added in GLFW 1.0. - * - * @par - * __GLFW 3:__ Added window handle parameter. + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. * * @ingroup window */ @@ -3224,11 +3876,11 @@ /*! @brief Sets the swap interval for the current context. * - * This function sets the swap interval for the current context, i.e. the - * number of screen updates to wait from the time @ref glfwSwapBuffers was - * called before swapping the buffers and returning. This is sometimes called - * _vertical synchronization_, _vertical retrace synchronization_ or just - * _vsync_. + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. * * Contexts that support either of the `WGL_EXT_swap_control_tear` and * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals, @@ -3240,25 +3892,30 @@ * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * * @param[in] interval The minimum number of screen updates to wait for * until the buffers are swapped by @ref glfwSwapBuffers. * - * @note This function is not called during window creation, leaving the swap - * interval set to whatever is the default on that platform. This is done + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done * because some swap interval extensions used by GLFW do not allow the swap * interval to be reset to zero once it has been set to a non-zero value. * - * @note Some GPU drivers do not honor the requested swap interval, either - * because of user settings that override the request or due to bugs in the - * driver. + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. * - * @par Thread Safety - * This function may be called from any thread. + * @thread_safety This function may be called from any thread. * * @sa @ref buffer_swap * @sa glfwSwapBuffers * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3268,8 +3925,8 @@ * * This function returns whether the specified * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for OpenGL and OpenGL ES extension and - * platform-specific context creation API extensions. + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. @@ -3279,16 +3936,24 @@ * frequently. The extension strings will not change during the lifetime of * a context, so there is no danger in doing this. * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise. + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. * - * @par Thread Safety - * This function may be called from any thread. + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwGetProcAddress * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ @@ -3297,36 +3962,243 @@ /*! @brief Returns the address of the specified function for the current * context. * - * This function returns the address of the specified - * [client API or extension function](@ref context_glext), if it is supported + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported * by the current context. * * A context must be current on the calling thread. Calling this function * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if the function is - * unavailable or an [error](@ref error_handling) occurred. + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. * - * @note The addresses of a given function is not guaranteed to be the same + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same * between contexts. * - * @par Pointer Lifetime - * The returned function pointer is valid until the context is destroyed or the - * library is terminated. + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. * - * @par Thread Safety - * This function may be called from any thread. + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. * * @sa @ref context_glext * @sa glfwExtensionSupported * - * @since Added in GLFW 1.0. + * @since Added in version 1.0. * * @ingroup context */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Returns whether the Vulkan loader has been found. + * + * This function returns whether the Vulkan loader has been found. This check + * is performed by @ref glfwInit. + * + * The availability of a Vulkan loader does not by itself guarantee that window + * surface creation or even device creation is possible. Call @ref + * glfwGetRequiredInstanceExtensions to check whether the extensions necessary + * for Vulkan surface creation are available and @ref + * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of + * a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contains `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remarks Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader was not found at initialization, this function returns + * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE + * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was + * found. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remarks If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + /************************************************************************* * Global definition cleanup diff --git a/examples/libs/glfw/include/GLFW/glfw3native.h b/examples/libs/glfw/include/GLFW/glfw3native.h index b3ce748..9fa955e 100644 --- a/examples/libs/glfw/include/GLFW/glfw3native.h +++ b/examples/libs/glfw/include/GLFW/glfw3native.h @@ -1,5 +1,5 @@ /************************************************************************* - * GLFW 3.1 - www.glfw.org + * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard @@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** * - * Before the inclusion of @ref glfw3native.h, you must define exactly one - * window system API macro and exactly one context creation API macro. Failure - * to do this will cause a compile-time error. + * Before the inclusion of @ref glfw3native.h, you may define exactly one + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL` @@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include #include -#else - #error "No window API selected" +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#elif defined(GLFW_EXPOSE_NATIVE_MIR) + #include #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */ -#elif defined(GLFW_EXPOSE_NATIVE_NSGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */ -#elif defined(GLFW_EXPOSE_NATIVE_GLX) +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) #include -#elif defined(GLFW_EXPOSE_NATIVE_EGL) +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) #include -#else - #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.1. + * @since Added in version 3.1. * * @ingroup native */ @@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -290,15 +292,116 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_MIR) +/*! @brief Returns the `MirConnection*` used by GLFW. + * + * @return The `MirConnection*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirConnection* glfwGetMirDisplay(void); + +/*! @brief Returns the Mir output ID of the specified monitor. + * + * @return The Mir output ID of the specified monitor, or zero if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `MirSurface*` of the specified window. + * + * @return The `MirSurface*` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); #endif #if defined(GLFW_EXPOSE_NATIVE_EGL) @@ -307,11 +410,10 @@ * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ @@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. * - * @par Thread Safety - * This function may be called from any thread. Access is not synchronized. + * @thread_safety This function may be called from any thread. Access is not + * synchronized. * - * @par History - * Added in GLFW 3.0. + * @since Added in version 3.0. * * @ingroup native */ diff --git a/examples/libs/glfw/lib-vc2010-32/glfw3.lib b/examples/libs/glfw/lib-vc2010-32/glfw3.lib index 014458e..348abec 100644 --- a/examples/libs/glfw/lib-vc2010-32/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-32/glfw3.lib Binary files differ diff --git a/examples/libs/glfw/lib-vc2010-64/glfw3.lib b/examples/libs/glfw/lib-vc2010-64/glfw3.lib index 8cdda39..768f308 100644 --- a/examples/libs/glfw/lib-vc2010-64/glfw3.lib +++ b/examples/libs/glfw/lib-vc2010-64/glfw3.lib Binary files differ diff --git a/examples/vulkan_example/CMakeLists.txt b/examples/vulkan_example/CMakeLists.txt new file mode 100644 index 0000000..3657c82 --- /dev/null +++ b/examples/vulkan_example/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 2.8) +project(ImGuiGLFWVulkanExample C CXX) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) +endif() + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DVK_PROTOTYPES") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_PROTOTYPES") + +# GLFW +set(GLFW_DIR ../../../glfw) # Set this to point to a up-to-date GLFW repo +option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) +option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) +option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) +option(GLFW_INSTALL "Generate installation target" OFF) +option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) +add_subdirectory(${GLFW_DIR} binary_dir EXCLUDE_FROM_ALL) +include_directories(${GLFW_DIR}/include) + +# ImGui +set(IMGUI_DIR ../../) +include_directories(${IMGUI_DIR}) + +# Libraries +find_library(VULKAN_LIBRARY + NAMES vulkan vulkan-1) +set(LIBRARIES "glfw;${VULKAN_LIBRARY}") + +# Use vulkan headers from glfw: +include_directories(${GLFW_DIR}/deps) + +file(GLOB sources *.cpp) + +add_executable(vulkan_example ${sources} ${IMGUI_DIR}/imgui.cpp ${IMGUI_DIR}/imgui_draw.cpp ${IMGUI_DIR}/imgui_demo.cpp) +target_link_libraries(vulkan_example ${LIBRARIES}) diff --git a/examples/vulkan_example/build_win32.bat b/examples/vulkan_example/build_win32.bat new file mode 100644 index 0000000..e8b5a6c --- /dev/null +++ b/examples/vulkan_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I ..\libs\glfw\include /I %VULKAN_SDK%\include *.cpp ..\..\*.cpp /FeDebug/vulkan_example.exe /FoDebug/ /link /LIBPATH:..\libs\glfw\lib-vc2010-32 /libpath:%VULKAN_SDK%\bin32 glfw3.lib opengl32.lib gdi32.lib shell32.lib vulkan-1.lib + diff --git a/examples/vulkan_example/gen_spv.sh b/examples/vulkan_example/gen_spv.sh new file mode 100755 index 0000000..f95f8fa --- /dev/null +++ b/examples/vulkan_example/gen_spv.sh @@ -0,0 +1,4 @@ +#!/bin/bash +glslangValidator -V -o glsl_shader.frag.spv glsl_shader.frag +glslangValidator -V -o glsl_shader.vert.spv glsl_shader.vert +spirv-remap --map all --dce all --strip-all --input glsl_shader.frag.spv glsl_shader.vert.spv --output ./ diff --git a/examples/vulkan_example/glsl_shader.frag b/examples/vulkan_example/glsl_shader.frag new file mode 100644 index 0000000..8205b67 --- /dev/null +++ b/examples/vulkan_example/glsl_shader.frag @@ -0,0 +1,14 @@ +#version 450 core +layout(location = 0, index = 0) out vec4 fColor; + +layout(set=0, binding=0) uniform sampler2D sTexture; + +in block{ + vec4 Color; + vec2 UV; +} In; + +void main() +{ + fColor = In.Color * texture(sTexture, In.UV.st); +} diff --git a/examples/vulkan_example/glsl_shader.vert b/examples/vulkan_example/glsl_shader.vert new file mode 100644 index 0000000..55098fe --- /dev/null +++ b/examples/vulkan_example/glsl_shader.vert @@ -0,0 +1,21 @@ +#version 450 core +layout(location = 0) in vec2 aPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec4 aColor; + +layout(push_constant) uniform uPushConstant{ + vec2 uScale; + vec2 uTranslate; +} pc; + +out block{ + vec4 Color; + vec2 UV; +} Out; + +void main() +{ + Out.Color = aColor; + Out.UV = aUV; + gl_Position = vec4(aPos*pc.uScale+pc.uTranslate, 0, 1); +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp new file mode 100644 index 0000000..33d8e99 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -0,0 +1,935 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// GLFW +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include +#ifdef _WIN32 +#undef APIENTRY +#define GLFW_EXPOSE_NATIVE_WIN32 +#define GLFW_EXPOSE_NATIVE_WGL +#include +#endif + +#include "imgui_impl_glfw_vulkan.h" + +// GLFW Data +static GLFWwindow* g_Window = NULL; +static double g_Time = 0.0f; +static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseWheel = 0.0f; + +// Vulkan Data +static VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; + +static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; +static size_t g_BufferMemoryAlignment = 256; +static VkPipelineCreateFlags g_PipelineCreateFlags = 0; +static int g_FrameIndex = 0; + +static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE; +static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE; +static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE; +static VkPipeline g_Pipeline = VK_NULL_HANDLE; + +static VkSampler g_FontSampler = VK_NULL_HANDLE; +static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE; +static VkImage g_FontImage = VK_NULL_HANDLE; +static VkImageView g_FontView = VK_NULL_HANDLE; + +static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; + +static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE; +static VkBuffer g_UploadBuffer = VK_NULL_HANDLE; + +static unsigned char __glsl_shader_vert_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x02, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, + 0x2e, 0x34, 0x35, 0x30, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x41, 0x14, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x05, 0x00, 0xb1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x80, 0x14, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x06, 0x04, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x03, 0x00, 0x06, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x21, 0x00, 0x03, 0x00, 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x16, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x17, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x47, 0x11, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x9a, 0x02, 0x00, 0x00, 0x41, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9b, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x6a, 0x16, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x91, 0x02, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, + 0x0b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x7f, 0x02, 0x00, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00, + 0xb1, 0x02, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x7f, 0x02, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x2e, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x00, 0x00, + 0x3b, 0x00, 0x04, 0x00, 0x2e, 0x05, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x06, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x83, 0x06, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x92, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, + 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x05, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x05, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x60, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x41, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0xaa, 0x26, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xaa, 0x26, 0x00, 0x00, 0x71, 0x4e, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x6a, 0x16, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x91, 0x02, 0x00, 0x00, + 0xea, 0x50, 0x00, 0x00, 0x47, 0x11, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0xea, 0x50, 0x00, 0x00, 0xda, 0x35, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, + 0x80, 0x14, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0xfa, 0x16, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3d, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0xef, 0x56, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0xc7, 0x35, 0x00, 0x00, 0xe0, 0x29, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x92, 0x02, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0xfa, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x42, 0x2c, 0x00, 0x00, + 0x81, 0x00, 0x05, 0x00, 0x13, 0x00, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0xa0, 0x22, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0xa1, 0x41, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x84, 0x36, 0x00, 0x00, 0xd1, 0x4e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x07, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xa1, 0x41, 0x00, 0x00, 0x84, 0x36, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, + 0x8a, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x9b, 0x02, 0x00, 0x00, + 0x17, 0x2f, 0x00, 0x00, 0x42, 0x13, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, + 0x3e, 0x00, 0x03, 0x00, 0x17, 0x2f, 0x00, 0x00, 0x54, 0x47, 0x00, 0x00, + 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_vert_spv_len = 1172; + +static unsigned char __glsl_shader_frag_spv[] = +{ + 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x08, 0x00, + 0x6c, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x47, 0x00, 0x04, 0x00, 0x7a, 0x0c, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x1a, 0x04, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, + 0x02, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, + 0x0d, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x9a, 0x02, 0x00, 0x00, + 0x7a, 0x0c, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x04, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x97, 0x06, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, + 0x97, 0x06, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x09, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1b, 0x00, 0x03, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x7b, 0x04, 0x00, 0x00, + 0xec, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x04, 0x00, 0x90, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x1f, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, + 0xf8, 0x00, 0x02, 0x00, 0x6b, 0x5d, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, + 0x9b, 0x02, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x35, 0x16, 0x00, 0x00, + 0x0b, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x0b, 0x40, 0x00, 0x00, 0x8d, 0x1b, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0xfe, 0x01, 0x00, 0x00, 0xc0, 0x36, 0x00, 0x00, 0xec, 0x14, 0x00, 0x00, + 0x41, 0x00, 0x05, 0x00, 0x90, 0x02, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x35, 0x16, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, + 0x13, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0xc2, 0x43, 0x00, 0x00, + 0x57, 0x00, 0x05, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xb9, 0x46, 0x00, 0x00, + 0xc0, 0x36, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, + 0x1d, 0x00, 0x00, 0x00, 0xe4, 0x23, 0x00, 0x00, 0x0b, 0x40, 0x00, 0x00, + 0xb9, 0x46, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x7a, 0x0c, 0x00, 0x00, + 0xe4, 0x23, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00 +}; +static unsigned int __glsl_shader_frag_spv_len = 660; + +static uint32_t ImGui_ImplGlfwVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) +{ + VkPhysicalDeviceMemoryProperties prop; + vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + for (uint32_t i = 0; i < prop.memoryTypeCount; i++) + if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<TotalVtxCount * sizeof(ImDrawVert); + if (!g_VertexBuffer[g_FrameIndex] || g_VertexBufferSize[g_FrameIndex] < vertex_size) + { + if (g_VertexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); + if (g_VertexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); + size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = vertex_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_VertexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_VertexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_VertexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_VertexBuffer[g_FrameIndex], g_VertexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_VertexBufferSize[g_FrameIndex] = vertex_buffer_size; + } + + // Create the Index Buffer: + size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx); + if (!g_IndexBuffer[g_FrameIndex] || g_IndexBufferSize[g_FrameIndex] < index_size) + { + if (g_IndexBuffer[g_FrameIndex]) + vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); + if (g_IndexBufferMemory[g_FrameIndex]) + vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); + size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = index_buffer_size; + buffer_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_IndexBuffer[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_IndexBuffer[g_FrameIndex], &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_IndexBufferMemory[g_FrameIndex]); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_IndexBuffer[g_FrameIndex], g_IndexBufferMemory[g_FrameIndex], 0); + ImGui_ImplGlfwVulkan_VkResult(err); + g_IndexBufferSize[g_FrameIndex] = index_buffer_size; + } + + // Upload Vertex and index Data: + { + ImDrawVert* vtx_dst; + ImDrawIdx* idx_dst; + err = vkMapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], 0, vertex_size, 0, (void**)(&vtx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkMapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], 0, index_size, 0, (void**)(&idx_dst)); + ImGui_ImplGlfwVulkan_VkResult(err); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_VertexBufferMemory[g_FrameIndex]; + range[0].size = vertex_size; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = g_IndexBufferMemory[g_FrameIndex]; + range[1].size = index_size; + err = vkFlushMappedMemoryRanges(g_Device, 2, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_VertexBufferMemory[g_FrameIndex]); + vkUnmapMemory(g_Device, g_IndexBufferMemory[g_FrameIndex]); + } + + // Bind pipeline and descriptor sets: + { + vkCmdBindPipeline(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_Pipeline); + VkDescriptorSet desc_set[1] = {g_DescriptorSet}; + vkCmdBindDescriptorSets(g_CommandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL); + } + + // Bind Vertex And Index Buffer: + { + VkBuffer vertex_buffers[1] = {g_VertexBuffer[g_FrameIndex]}; + VkDeviceSize vertex_offset[1] = {0}; + vkCmdBindVertexBuffers(g_CommandBuffer, 0, 1, vertex_buffers, vertex_offset); + vkCmdBindIndexBuffer(g_CommandBuffer, g_IndexBuffer[g_FrameIndex], 0, VK_INDEX_TYPE_UINT16); + } + + // Setup viewport: + { + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = ImGui::GetIO().DisplaySize.x; + viewport.height = ImGui::GetIO().DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + vkCmdSetViewport(g_CommandBuffer, 0, 1, &viewport); + } + + // Setup scale and translation: + { + float scale[2]; + scale[0] = 2.0f/io.DisplaySize.x; + scale[1] = 2.0f/io.DisplaySize.y; + float translate[2]; + translate[0] = -1.0f; + translate[1] = -1.0f; + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale); + vkCmdPushConstants(g_CommandBuffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate); + } + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + VkRect2D scissor; + scissor.offset.x = static_cast(pcmd->ClipRect.x); + scissor.offset.y = static_cast(pcmd->ClipRect.y); + scissor.extent.width = static_cast(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = static_cast(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // TODO: + 1?????? + vkCmdSetScissor(g_CommandBuffer, 0, 1, &scissor); + vkCmdDrawIndexed(g_CommandBuffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +static const char* ImGui_ImplGlfwVulkan_GetClipboardText() +{ + return glfwGetClipboardString(g_Window); +} + +static void ImGui_ImplGlfwVulkan_SetClipboardText(const char* text) +{ + glfwSetClipboardString(g_Window, text); +} + +void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +{ + if (action == GLFW_PRESS && button >= 0 && button < 3) + g_MousePressed[button] = true; +} + +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +{ + g_MouseWheel += (float)yoffset; // Use fractional mouse wheel, 1.0 unit 5 lines. +} + +void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +{ + ImGuiIO& io = ImGui::GetIO(); + if (action == GLFW_PRESS) + io.KeysDown[key] = true; + if (action == GLFW_RELEASE) + io.KeysDown[key] = false; + + (void)mods; // Modifiers are not reliable across systems + io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL]; + io.KeyShift = io.KeysDown[GLFW_KEY_LEFT_SHIFT] || io.KeysDown[GLFW_KEY_RIGHT_SHIFT]; + io.KeyAlt = io.KeysDown[GLFW_KEY_LEFT_ALT] || io.KeysDown[GLFW_KEY_RIGHT_ALT]; + io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; +} + +void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +{ + ImGuiIO& io = ImGui::GetIO(); + if (c > 0 && c < 0x10000) + io.AddInputCharacter((unsigned short)c); +} + +bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer) +{ + ImGuiIO& io = ImGui::GetIO(); + + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + size_t upload_size = width*height*4*sizeof(char); + + VkResult err; + + // Create the Image: + { + VkImageCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + info.imageType = VK_IMAGE_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.extent.width = width; + info.extent.height = height; + info.extent.depth = 1; + info.mipLevels = 1; + info.arrayLayers = 1; + info.samples = VK_SAMPLE_COUNT_1_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetImageMemoryRequirements(g_Device, g_FontImage, &req); + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create the Image View: + { + VkResult err; + VkImageViewCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + info.image = g_FontImage; + info.viewType = VK_IMAGE_VIEW_TYPE_2D; + info.format = VK_FORMAT_R8G8B8A8_UNORM; + info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + info.subresourceRange.levelCount = 1; + info.subresourceRange.layerCount = 1; + err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Update the Descriptor Set: + { + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = g_FontSampler; + desc_image[0].imageView = g_FontView; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = g_DescriptorSet; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL); + } + + // Create the Upload Buffer: + { + VkBufferCreateInfo buffer_info = {}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = upload_size; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer); + ImGui_ImplGlfwVulkan_VkResult(err); + VkMemoryRequirements req; + vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req); + g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment; + VkMemoryAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = req.size; + alloc_info.memoryTypeIndex = ImGui_ImplGlfwVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits); + err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory); + ImGui_ImplGlfwVulkan_VkResult(err); + err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Upload to Buffer: + { + char* map = NULL; + err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map)); + ImGui_ImplGlfwVulkan_VkResult(err); + memcpy(map, pixels, upload_size); + VkMappedMemoryRange range[1] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = g_UploadBufferMemory; + range[0].size = upload_size; + err = vkFlushMappedMemoryRanges(g_Device, 1, range); + ImGui_ImplGlfwVulkan_VkResult(err); + vkUnmapMemory(g_Device, g_UploadBufferMemory); + } + // Copy to Image: + { + VkImageMemoryBarrier copy_barrier[1] = {}; + copy_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + copy_barrier[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + copy_barrier[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; + copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier[0].image = g_FontImage; + copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier[0].subresourceRange.levelCount = 1; + copy_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, 1, copy_barrier); + + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + VkImageMemoryBarrier use_barrier[1] = {}; + use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + use_barrier[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + use_barrier[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + use_barrier[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; + use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier[0].image = g_FontImage; + use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier[0].subresourceRange.levelCount = 1; + use_barrier[0].subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, NULL, 0, NULL, 1, use_barrier); + } + + // Store our identifier + io.Fonts->TexID = (void *)(intptr_t)g_FontImage; + + return true; +} + +bool ImGui_ImplGlfwVulkan_CreateDeviceObjects() +{ + VkResult err; + VkShaderModule vert_module; + VkShaderModule frag_module; + + // Create The Shader Modules: + { + VkShaderModuleCreateInfo vert_info = {}; + vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + vert_info.codeSize = __glsl_shader_vert_spv_len; + vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module); + ImGui_ImplGlfwVulkan_VkResult(err); + VkShaderModuleCreateInfo frag_info = {}; + frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + frag_info.codeSize = __glsl_shader_frag_spv_len; + frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_FontSampler) + { + VkSamplerCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + info.magFilter = VK_FILTER_LINEAR; + info.minFilter = VK_FILTER_LINEAR; + info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + info.minLod = -1000; + info.maxLod = 1000; + err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_DescriptorSetLayout) + { + VkSampler sampler[1] = {g_FontSampler}; + VkDescriptorSetLayoutBinding binding[1] = {}; + binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + binding[0].descriptorCount = 1; + binding[0].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + binding[0].pImmutableSamplers = sampler; + VkDescriptorSetLayoutCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + info.bindingCount = 1; + info.pBindings = binding; + err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + // Create Descriptor Set: + { + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = g_DescriptorPool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &g_DescriptorSetLayout; + err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + if (!g_PipelineLayout) + { + VkPushConstantRange push_constants[2] = {}; + push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[0].offset = sizeof(float) * 0; + push_constants[0].size = sizeof(float) * 2; + push_constants[1].stageFlags = VK_SHADER_STAGE_VERTEX_BIT; + push_constants[1].offset = sizeof(float) * 2; + push_constants[1].size = sizeof(float) * 2; + VkDescriptorSetLayout set_layout[1] = {g_DescriptorSetLayout}; + VkPipelineLayoutCreateInfo layout_info = {}; + layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_info.setLayoutCount = 1; + layout_info.pSetLayouts = set_layout; + layout_info.pushConstantRangeCount = 2; + layout_info.pPushConstantRanges = push_constants; + err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout); + ImGui_ImplGlfwVulkan_VkResult(err); + } + + VkPipelineShaderStageCreateInfo stage[2] = {}; + stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stage[0].module = vert_module; + stage[0].pName = "main"; + stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stage[1].module = frag_module; + stage[1].pName = "main"; + + VkVertexInputBindingDescription binding_desc[1] = {}; + binding_desc[0].stride = sizeof(ImDrawVert); + binding_desc[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + VkVertexInputAttributeDescription attribute_desc[3] = {}; + attribute_desc[0].location = 0; + attribute_desc[0].binding = binding_desc[0].binding; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = (size_t)(&((ImDrawVert*)0)->pos); + attribute_desc[1].location = 1; + attribute_desc[1].binding = binding_desc[0].binding; + attribute_desc[1].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[1].offset = (size_t)(&((ImDrawVert*)0)->uv); + attribute_desc[2].location = 2; + attribute_desc[2].binding = binding_desc[0].binding; + attribute_desc[2].format = VK_FORMAT_R8G8B8A8_UNORM; + attribute_desc[2].offset = (size_t)(&((ImDrawVert*)0)->col); + + VkPipelineVertexInputStateCreateInfo vertex_info = {}; + vertex_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_info.vertexBindingDescriptionCount = 1; + vertex_info.pVertexBindingDescriptions = binding_desc; + vertex_info.vertexAttributeDescriptionCount = 3; + vertex_info.pVertexAttributeDescriptions = attribute_desc; + + VkPipelineInputAssemblyStateCreateInfo ia_info = {}; + ia_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + ia_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkPipelineViewportStateCreateInfo viewport_info = {}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.scissorCount = 1; + + VkPipelineRasterizationStateCreateInfo raster_info = {}; + raster_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + raster_info.polygonMode = VK_POLYGON_MODE_FILL; + raster_info.cullMode = VK_CULL_MODE_NONE; + raster_info.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo ms_info = {}; + ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + ms_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_attachment[1] = {}; + color_attachment[0].blendEnable = VK_TRUE; + color_attachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_attachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].colorBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_attachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_attachment[0].alphaBlendOp = VK_BLEND_OP_ADD; + color_attachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo blend_info = {}; + blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + blend_info.attachmentCount = 1; + blend_info.pAttachments = color_attachment; + + VkDynamicState dynamic_states[2] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.dynamicStateCount = 2; + dynamic_state.pDynamicStates = dynamic_states; + + VkGraphicsPipelineCreateInfo info = {}; + info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + info.flags = g_PipelineCreateFlags; + info.stageCount = 2; + info.pStages = stage; + info.pVertexInputState = &vertex_info; + info.pInputAssemblyState = &ia_info; + info.pViewportState = &viewport_info; + info.pRasterizationState = &raster_info; + info.pMultisampleState = &ms_info; + info.pColorBlendState = &blend_info; + info.pDynamicState = &dynamic_state; + info.layout = g_PipelineLayout; + info.renderPass = g_RenderPass; + err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline); + ImGui_ImplGlfwVulkan_VkResult(err); + + vkDestroyShaderModule(g_Device, vert_module, g_Allocator); + vkDestroyShaderModule(g_Device, frag_module, g_Allocator); + + return true; +} + +void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects() +{ + if (g_UploadBuffer) + { + vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator); + g_UploadBuffer = VK_NULL_HANDLE; + } + if (g_UploadBufferMemory) + { + vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator); + g_UploadBufferMemory = VK_NULL_HANDLE; + } +} + +void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() +{ + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + for (int i=0; iallocator; + g_Gpu = init_data->gpu; + g_Device = init_data->device; + g_RenderPass = init_data->render_pass; + g_PipelineCache = init_data->pipeline_cache; + g_DescriptorPool = init_data->descriptor_pool; + g_CheckVkResult = init_data->check_vk_result; + + g_Window = window; + + ImGuiIO& io = ImGui::GetIO(); + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; + io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; + io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; + io.KeyMap[ImGuiKey_DownArrow] = GLFW_KEY_DOWN; + io.KeyMap[ImGuiKey_PageUp] = GLFW_KEY_PAGE_UP; + io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; + io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; + io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; + io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; + io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; + io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; + io.KeyMap[ImGuiKey_C] = GLFW_KEY_C; + io.KeyMap[ImGuiKey_V] = GLFW_KEY_V; + io.KeyMap[ImGuiKey_X] = GLFW_KEY_X; + io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; + io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; + + io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; +#ifdef _WIN32 + io.ImeWindowHandle = glfwGetWin32Window(g_Window); +#endif + + if (install_callbacks) + { + glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); + } + + ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + + return true; +} + +void ImGui_ImplGlfwVulkan_Shutdown() +{ + ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); + ImGui::Shutdown(); +} + +void ImGui_ImplGlfwVulkan_NewFrame() +{ + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + int w, h; + int display_w, display_h; + glfwGetWindowSize(g_Window, &w, &h); + glfwGetFramebufferSize(g_Window, &display_w, &display_h); + io.DisplaySize = ImVec2((float)w, (float)h); + io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); + + // Setup time step + double current_time = glfwGetTime(); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + g_Time = current_time; + + // Setup inputs + // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) + if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } + else + { + io.MousePos = ImVec2(-1,-1); + } + + for (int i = 0; i < 3; i++) + { + io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MousePressed[i] = false; + } + + io.MouseWheel = g_MouseWheel; + g_MouseWheel = 0.0f; + + // Hide OS mouse cursor if ImGui is drawing it + glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + + // Start the frame + ImGui::NewFrame(); +} +void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) +{ + g_CommandBuffer = command_buffer; + ImGui::Render(); + g_CommandBuffer = VK_NULL_HANDLE; + g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; +} diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h new file mode 100644 index 0000000..74d35a2 --- /dev/null +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -0,0 +1,40 @@ +// ImGui GLFW binding with Vulkan + shaders +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +struct GLFWwindow; + +#define IMGUI_VK_QUEUED_FRAMES 2 + +struct ImGui_ImplGlfwVulkan_Init_Data +{ + VkAllocationCallbacks* allocator; + VkPhysicalDevice gpu; + VkDevice device; + VkRenderPass render_pass; + VkPipelineCache pipeline_cache; + VkDescriptorPool descriptor_pool; + void (*check_vk_result)(VkResult err); +}; + +IMGUI_API bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data); +IMGUI_API void ImGui_ImplGlfwVulkan_Shutdown(); +IMGUI_API void ImGui_ImplGlfwVulkan_NewFrame(); +IMGUI_API void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); +IMGUI_API void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); +IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects(); + +// GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) +// Provided here if you want to chain callbacks. +// You can also handle inputs yourself and use those as a reference. +IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c); + diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp new file mode 100644 index 0000000..130fd87 --- /dev/null +++ b/examples/vulkan_example/main.cpp @@ -0,0 +1,539 @@ +// ImGui - standalone example application for Glfw + Vulkan, using programmable pipeline +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. + +#include + +#include // printf, fprintf +#include // abort +#define GLFW_INCLUDE_NONE +#define GLFW_INCLUDE_VULKAN +#include + +#include "imgui_impl_glfw_vulkan.h" + +#define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 + +static VkAllocationCallbacks* g_Allocator = NULL; +static VkInstance g_Instance = VK_NULL_HANDLE; +static VkSurfaceKHR g_Surface = VK_NULL_HANDLE; +static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static uint32_t g_QueueFamily = 0; +static VkQueue g_Queue = VK_NULL_HANDLE; + +static VkFormat g_Format = VK_FORMAT_B8G8R8A8_UNORM; +static VkColorSpaceKHR g_ColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; +static VkImageSubresourceRange g_ImageRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; + +static int fb_width, fb_height; +static uint32_t g_BackBufferIndex = 0; +static uint32_t g_BackBufferCount = 0; +static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkImageView g_BackBufferView[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; +static VkFramebuffer g_Framebuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; + +static uint32_t g_FrameIndex = 0; +static VkCommandPool g_CommandPool[IMGUI_VK_QUEUED_FRAMES]; +static VkCommandBuffer g_CommandBuffer[IMGUI_VK_QUEUED_FRAMES]; +static VkFence g_Fence[IMGUI_VK_QUEUED_FRAMES]; +static VkSemaphore g_Semaphore[IMGUI_VK_QUEUED_FRAMES]; + +static VkClearValue g_ClearValue = {}; + +static void check_vk_result(VkResult err) +{ + if (err == 0) return; + printf("VkResult %d\n", err); + if (err < 0) + abort(); +} + +static void resize_vulkan(GLFWwindow* /*window*/, int w, int h) +{ + VkResult err; + VkSwapchainKHR old_swapchain = g_Swapchain; + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + + // Destroy old Framebuffer: + for (uint32_t i=0; iAddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + + // Upload Fonts + { + VkResult err; + err = vkResetCommandPool(g_Device, g_CommandPool[g_FrameIndex], 0); + check_vk_result(err); + VkCommandBufferBeginInfo begin_info = {}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + err = vkBeginCommandBuffer(g_CommandBuffer[g_FrameIndex], &begin_info); + check_vk_result(err); + + ImGui_ImplGlfwVulkan_CreateFontsTexture(g_CommandBuffer[g_FrameIndex]); + + VkSubmitInfo end_info = {}; + end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + end_info.commandBufferCount = 1; + end_info.pCommandBuffers = &g_CommandBuffer[g_FrameIndex]; + err = vkEndCommandBuffer(g_CommandBuffer[g_FrameIndex]); + check_vk_result(err); + err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE); + check_vk_result(err); + + err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); + } + + bool show_test_window = true; + bool show_another_window = false; + ImVec4 clear_color = ImColor(114, 144, 154); + + // Main loop + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + ImGui_ImplGlfwVulkan_NewFrame(); + + // 1. Show a simple window + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + { + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::ColorEdit3("clear color", (float*)&clear_color); + if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) + { + ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); + ImGui::ShowTestWindow(&show_test_window); + } + + g_ClearValue.color.float32[0] = clear_color.x; + g_ClearValue.color.float32[1] = clear_color.y; + g_ClearValue.color.float32[2] = clear_color.z; + g_ClearValue.color.float32[3] = clear_color.w; + + frame_begin(); + ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); + frame_end(); + } + + // Cleanup + VkResult err = vkDeviceWaitIdle(g_Device); + check_vk_result(err); + ImGui_ImplGlfwVulkan_Shutdown(); + cleanup_vulkan(); + glfwTerminate(); + + return 0; +} diff --git a/imgui.cpp b/imgui.cpp index 8f2b87f..316dea5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (main code and documentation) // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. @@ -152,6 +152,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337). + - 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337) - 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). - 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert. - 2016/02/21 (1.48) - removed ColorEditMode() and ImGuiColorEditMode in favor of ImGuiColorEditFlags and parameters to ColorEdit*() functions @@ -506,6 +508,7 @@ - color: add a better color picker (#346) - node/graph editor (#306) - pie menus patterns (#434) + - drag'n drop, dragging helpers (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479) - plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals) - plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots) - plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value) @@ -694,13 +697,12 @@ WindowMinSize = ImVec2(32,32); // Minimum window size WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text - ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows + ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets) FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets). ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin() IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -715,8 +717,9 @@ Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); + Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f); Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input @@ -754,7 +757,6 @@ Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); - Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f); Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); } @@ -1652,7 +1654,7 @@ { ImGuiState& g = *GImGui; IM_ASSERT(g.CurrentWindowStack.Size >= 2); - return g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; + return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) @@ -2339,9 +2341,9 @@ // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = 2 bytes = 64K vertices) // If this assert triggers because you are drawing lots of stuff manually, A) workaround by calling BeginChild()/EndChild() to put your draw commands in multiple draw lists, B) #define ImDrawIdx to a 'unsigned int' in imconfig.h and render accordingly. - IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. - IM_ASSERT((unsigned long long int)draw_list->_VtxCurrentIdx <= ((unsigned long long int)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. - + IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); // Sanity check. Bug or mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc. + IM_ASSERT((int64_t)draw_list->_VtxCurrentIdx <= ((int64_t)1L << (sizeof(ImDrawIdx)*8))); // Too many vertices in same ImDrawList. See comment above. + out_render_list.push_back(draw_list); GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; @@ -3139,9 +3141,8 @@ void ImGui::BeginTooltip() { - ImGuiState& g = *GImGui; ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; - ImGui::Begin("##Tooltip", NULL, ImVec2(0,0), g.Style.Colors[ImGuiCol_TooltipBg].w, flags); + ImGui::Begin("##Tooltip", NULL, flags); } void ImGui::EndTooltip() @@ -3279,9 +3280,8 @@ ImFormatString(name, 20, "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth else ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame - float alpha = 1.0f; - bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), alpha, flags); + bool opened = ImGui::Begin(name, NULL, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders; if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display) @@ -3312,7 +3312,7 @@ } ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; - bool opened = ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), -1.0f, flags); + bool opened = ImGui::Begin(name, p_opened, flags); if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display) { ImGui::EndPopup(); @@ -3392,8 +3392,7 @@ char title[256]; ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id); - const float alpha = 1.0f; - bool ret = ImGui::Begin(title, NULL, size, alpha, flags); + bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; @@ -3443,13 +3442,14 @@ const ImGuiStyle& style = g.Style; ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]); ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding); - return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove | extra_flags); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags); } void ImGui::EndChildFrame() { ImGui::EndChild(); - ImGui::PopStyleVar(); + ImGui::PopStyleVar(2); ImGui::PopStyleColor(); } @@ -3692,10 +3692,6 @@ window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. - // Default alpha - if (bg_alpha < 0.0f) - bg_alpha = style.WindowFillAlphaDefault; - // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { @@ -3767,7 +3763,7 @@ } // Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects. - window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; + window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding; // Calculate auto-fit size ImVec2 size_auto_fit; @@ -3981,27 +3977,26 @@ } // Scrollbars - window->ScrollbarY = (flags & ImGuiWindowFlags_ForceVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_ForceHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f; // Window background - if (bg_alpha > 0.0f) - { - ImGuiCol col_idx; - if ((flags & ImGuiWindowFlags_ComboBox) != 0) - col_idx = ImGuiCol_ComboBg; - else if ((flags & ImGuiWindowFlags_Tooltip) != 0) - col_idx = ImGuiCol_TooltipBg; - else if ((flags & ImGuiWindowFlags_Popup) != 0) - col_idx = ImGuiCol_WindowBg; - else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) - col_idx = ImGuiCol_ChildWindowBg; - else - col_idx = ImGuiCol_WindowBg; - window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, GetColorU32(col_idx, bg_alpha), window_rounding); - } + // Default alpha + ImGuiCol bg_color_idx = ImGuiCol_WindowBg; + if ((flags & ImGuiWindowFlags_ComboBox) != 0) + bg_color_idx = ImGuiCol_ComboBg; + else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0) + bg_color_idx = ImGuiCol_PopupBg; + else if ((flags & ImGuiWindowFlags_ChildWindow) != 0) + bg_color_idx = ImGuiCol_ChildWindowBg; + ImVec4 bg_color = style.Colors[bg_color_idx]; + if (bg_alpha >= 0.0f) + bg_color.w = bg_alpha; + bg_color.w *= style.Alpha; + if (bg_color.w > 0.0f) + window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding); // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) @@ -4521,6 +4516,7 @@ case ImGuiCol_TextDisabled: return "TextDisabled"; case ImGuiCol_WindowBg: return "WindowBg"; case ImGuiCol_ChildWindowBg: return "ChildWindowBg"; + case ImGuiCol_PopupBg: return "PopupBg"; case ImGuiCol_Border: return "Border"; case ImGuiCol_BorderShadow: return "BorderShadow"; case ImGuiCol_FrameBg: return "FrameBg"; @@ -4558,7 +4554,6 @@ case ImGuiCol_PlotHistogram: return "PlotHistogram"; case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; - case ImGuiCol_TooltipBg: return "TooltipBg"; case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; } IM_ASSERT(0); @@ -7104,9 +7099,9 @@ static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; } -static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } #ifdef __APPLE__ // FIXME: Move setting to IO structure +static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; } static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } #else static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } @@ -7310,7 +7305,6 @@ return false; } draw_window = GetCurrentWindow(); - draw_window->DC.CursorPos += style.FramePadding; size.x -= draw_window->ScrollbarSizes.x; } else @@ -8501,7 +8495,7 @@ bool want_open = false, want_close = false; if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { - // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers so menus feel more reactive. + // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; if (g.HoveredWindow == window && g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) { diff --git a/imgui.h b/imgui.h index c7eaa1b..3641824 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.48 WIP" +#define IMGUI_VERSION "1.49 WIP" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API @@ -114,7 +114,7 @@ // Window IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // ". this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. + IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually. IMGUI_API void End(); // finish appending to current window, pop it off the window stack. IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " @@ -316,7 +316,7 @@ IMGUI_API void TreePush(const char* str_id = NULL); // already called by TreeNode(), but you can call Push/Pop yourself for layouting purpose IMGUI_API void TreePush(const void* ptr_id = NULL); // " IMGUI_API void TreePop(); - IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node to be opened. + IMGUI_API void SetNextTreeNodeOpened(bool opened, ImGuiSetCond cond = 0); // set next tree node/collapsing header to be opened. // Widgets: Selectable / Lists IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height @@ -467,11 +467,12 @@ ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar - ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You need to use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. + ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section. ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus) - ImGuiWindowFlags_ForceVerticalScrollbar = 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) - ImGuiWindowFlags_ForceHorizontalScrollbar=1 << 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) + ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) + ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() @@ -546,8 +547,9 @@ { ImGuiCol_Text, ImGuiCol_TextDisabled, - ImGuiCol_WindowBg, - ImGuiCol_ChildWindowBg, + ImGuiCol_WindowBg, // Background of normal windows + ImGuiCol_ChildWindowBg, // Background of child windows + ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows ImGuiCol_Border, ImGuiCol_BorderShadow, ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input @@ -585,7 +587,6 @@ ImGuiCol_PlotHistogram, ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, - ImGuiCol_TooltipBg, ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active ImGuiCol_COUNT }; @@ -667,7 +668,6 @@ ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! - float WindowFillAlphaDefault; // Default alpha of window background, if not specified in ImGui::Begin() float IndentSpacing; // Horizontal indentation when e.g. entering a tree node float ColumnsMinSpacing; // Minimum horizontal spacing between two columns float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar @@ -895,6 +895,7 @@ int CountGrep; ImGuiTextFilter(const char* default_filter = ""); + ~ImGuiTextFilter() {} void Clear() { InputBuf[0] = 0; Build(); } bool Draw(const char* label = "Filter (inc,-exc)", float width = 0.0f); // Helper calling InputText+Build bool PassFilter(const char* text, const char* text_end = NULL) const; @@ -1157,7 +1158,7 @@ // Stateful path API, add points then finish with PathFill() or PathStroke() inline void PathClear() { _Path.resize(0); } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } - inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || _Path[_Path.Size-1].x != pos.x || _Path[_Path.Size-1].y != pos.y) _Path.push_back(pos); } + inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } inline void PathFill(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 132e8e7..fdf2d8e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (demo code) // Don't remove this file from your project! It is useful reference code that you can execute. @@ -139,7 +139,6 @@ static bool no_scrollbar = false; static bool no_collapse = false; static bool no_menu = false; - static float bg_alpha = -0.01f; // <0: default // Demonstrate the various window flags. Typically you would just use the default. ImGuiWindowFlags window_flags = 0; @@ -150,7 +149,8 @@ if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; - if (!ImGui::Begin("ImGui Demo", p_opened, ImVec2(550,680), bg_alpha, window_flags)) + ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver); + if (!ImGui::Begin("ImGui Demo", p_opened, window_flags)) { // Early out if the window is collapsed, as an optimization. ImGui::End(); @@ -211,10 +211,6 @@ ImGui::Checkbox("No collapse", &no_collapse); ImGui::Checkbox("No menu", &no_menu); - ImGui::PushItemWidth(100); - ImGui::DragFloat("Window Fill Alpha", &bg_alpha, 0.005f, -0.01f, 1.0f, bg_alpha < 0.0f ? "(default)" : "%.3f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. - ImGui::PopItemWidth(); - if (ImGui::TreeNode("Style")) { ImGui::ShowStyleEditor(); @@ -1500,7 +1496,7 @@ ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); } ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("KeyMods: %s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); + ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false"); ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false"); @@ -1561,7 +1557,6 @@ ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f); if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f; ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero. - ImGui::DragFloat("Window Fill Alpha Default", &style.WindowFillAlphaDefault, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::PopItemWidth(); ImGui::TreePop(); } @@ -1618,7 +1613,7 @@ static ImGuiTextFilter filter; filter.Draw("Filter colors", 200); - ImGui::BeginChild("#colors", ImVec2(0, 300), true); + ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGui::PushItemWidth(-160); for (int i = 0; i < ImGuiCol_COUNT; i++) { @@ -2299,12 +2294,12 @@ { ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID. ImGui::AlignFirstTextHeightToWidgets(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high. - bool opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid); + bool is_opened = ImGui::TreeNode("Object", "%s_%u", prefix, uid); ImGui::NextColumn(); ImGui::AlignFirstTextHeightToWidgets(); ImGui::Text("my sailor is rich"); ImGui::NextColumn(); - if (opened) + if (is_opened) { static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f }; for (int i = 0; i < 8; i++) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 95871b6..1d26856 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (drawing and font code) // Contains implementation for diff --git a/imgui_internal.h b/imgui_internal.h index 384a846..65d766c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.48 WIP +// dear imgui, v1.49 WIP // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!